@minimalcorp/tsunagi 0.1.37 → 0.1.39

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 (129) hide show
  1. package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  2. package/.next/standalone/apps/web/.next/build-manifest.json +5 -5
  3. package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/apps/web/.next/server/app/_global-error/page/build-manifest.json +2 -2
  5. package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
  6. package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/standalone/apps/web/.next/server/app/_not-found/page/build-manifest.json +2 -2
  13. package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
  15. package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +2 -2
  16. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  17. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  18. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  21. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
  23. package/.next/standalone/apps/web/.next/server/app/index.rsc +3 -3
  24. package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  25. package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
  26. package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  27. package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
  28. package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  29. package/.next/standalone/apps/web/.next/server/app/page/build-manifest.json +2 -2
  30. package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
  31. package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/apps/web/.next/server/app/settings/page/build-manifest.json +2 -2
  33. package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  34. package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  35. package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
  36. package/.next/standalone/apps/web/.next/server/app/settings.rsc +3 -3
  37. package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  38. package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  39. package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  40. package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  41. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  42. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  43. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page/build-manifest.json +2 -2
  44. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  45. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0nhzci6._.js +4 -8
  47. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0vi01rl._.js +4 -8
  48. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__04g~n~m._.js → [root-of-the-server]__0zf09ry._.js} +2 -2
  49. package/.next/standalone/apps/web/.next/server/chunks/ssr/_04l3mh~._.js +10 -0
  50. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0bt-4.4._.js +3 -0
  51. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0e3431w._.js +10 -0
  52. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0g.cd6a._.js +1 -1
  53. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0lirkqp._.js +10 -0
  54. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0soxqr.._.js +3 -0
  55. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_settings_page_tsx_0i6itlb._.js +1 -1
  56. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_[id]_page_tsx_0jshsm2._.js +4 -5
  57. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0h0imx2._.js → node_modules_0_4__2k._.js} +1 -1
  58. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0pbr55t._.js → node_modules_0bqsyfk._.js} +1 -1
  59. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_06vr-0a._.js → node_modules_0bzw~9d._.js} +1 -1
  60. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0k7u4.c._.js → node_modules_0fsewd2._.js} +1 -1
  61. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0c6z_cw._.js → node_modules_0l~40og._.js} +1 -1
  62. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0jo-w3s._.js → node_modules_0pk6e0.._.js} +1 -1
  63. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0zkg-x0._.js → node_modules_0smdx~2._.js} +1 -1
  64. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0fcqekz._.js → node_modules_0uej915._.js} +1 -1
  65. package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +5 -5
  66. package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
  67. package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  68. package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
  69. package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
  70. package/.next/standalone/apps/web/.next/static/chunks/{094hkpbli0k9s.js → 02.u6zk77a338.js} +10 -11
  71. package/.next/standalone/apps/web/.next/static/chunks/05n6~h_wwg.jj.js +5 -0
  72. package/.next/standalone/apps/web/.next/static/chunks/0_ygv4z~5c_9z.js +5 -0
  73. package/.next/standalone/apps/web/.next/static/chunks/0g5hoj5w-z.~6.js +1 -0
  74. package/.next/standalone/apps/web/.next/static/chunks/0nhcl~svhi_26.js +7 -0
  75. package/.next/standalone/apps/web/.next/static/chunks/0p4dfdgz~3qt3.js +5 -0
  76. package/.next/standalone/apps/web/.next/static/chunks/0p9~lk406udl5.css +4 -0
  77. package/.next/standalone/apps/web/.next/static/chunks/0q-u7bl7oa42n.js +1 -0
  78. package/.next/standalone/apps/web/.next/static/chunks/0q_j4~6_etj_q.js +7 -0
  79. package/.next/standalone/apps/web/.next/static/chunks/0zjymvayyxt-d.js +5 -0
  80. package/.next/standalone/apps/web/.next/static/chunks/{0lp.2eizum8y~.js → 11rs2-0jl1rzr.js} +1 -1
  81. package/.next/standalone/apps/web/.next/static/chunks/{15~pc9ql1ab38.js → 158q94mo2-6sx.js} +7 -7
  82. package/.next/standalone/apps/web/.next/static/chunks/167xa3jy_0g.u.js +1 -0
  83. package/.next/standalone/apps/web/.next/static/chunks/{turbopack-0079niub0zo4u.js → turbopack-07pr2uza0.4cp.js} +1 -1
  84. package/dist/server/basic-auth.js +9 -1
  85. package/dist/server/generated/prisma/internal/class.js +1 -1
  86. package/dist/server/index.js +20 -0
  87. package/dist/server/lib/claude-command.d.ts +6 -0
  88. package/dist/server/lib/claude-command.js +85 -0
  89. package/dist/server/lib/claude-config-guard.d.ts +12 -0
  90. package/dist/server/lib/claude-config-guard.js +49 -0
  91. package/dist/server/lib/lmstudio.d.ts +24 -0
  92. package/dist/server/lib/lmstudio.js +198 -0
  93. package/dist/server/lib/local-llm-env.d.ts +28 -0
  94. package/dist/server/lib/local-llm-env.js +91 -0
  95. package/dist/server/lib/local-llm.d.ts +56 -0
  96. package/dist/server/lib/local-llm.js +366 -0
  97. package/dist/server/lib/ollama-settings.d.ts +16 -10
  98. package/dist/server/lib/ollama-settings.js +104 -91
  99. package/dist/server/lib/repositories/task.js +3 -0
  100. package/dist/server/lib/searxng.d.ts +26 -0
  101. package/dist/server/lib/searxng.js +308 -0
  102. package/dist/server/lib/services/task-service.js +1 -3
  103. package/dist/server/routes/local-llm.d.ts +2 -0
  104. package/dist/server/routes/local-llm.js +192 -0
  105. package/dist/server/routes/mcp-web.d.ts +2 -0
  106. package/dist/server/routes/mcp-web.js +107 -0
  107. package/dist/server/routes/onboarding.js +4 -4
  108. package/dist/server/routes/settings.js +100 -26
  109. package/dist/server/routes/tasks.js +5 -1
  110. package/dist/server/routes/terminal.js +77 -28
  111. package/npm-shrinkwrap.json +5 -5
  112. package/package.json +1 -1
  113. package/prisma/schema.prisma +1 -1
  114. package/.next/standalone/apps/web/.next/server/chunks/ssr/_016-lxb._.js +0 -3
  115. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0hh~0f6._.js +0 -3
  116. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0r0xwce._.js +0 -6
  117. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0sbp1da._.js +0 -6
  118. package/.next/standalone/apps/web/.next/server/chunks/ssr/_12c1w~~._.js +0 -6
  119. package/.next/standalone/apps/web/.next/static/chunks/0229rjr88pv9k.js +0 -1
  120. package/.next/standalone/apps/web/.next/static/chunks/04l9g6rg7~-d5.js +0 -1
  121. package/.next/standalone/apps/web/.next/static/chunks/0citvl2medd0s.js +0 -11
  122. package/.next/standalone/apps/web/.next/static/chunks/0e8u7rqrqfiiy.js +0 -1
  123. package/.next/standalone/apps/web/.next/static/chunks/0pg---_6a_4ls.css +0 -4
  124. package/.next/standalone/apps/web/.next/static/chunks/0uv~zl3--e3wo.js +0 -11
  125. package/.next/standalone/apps/web/.next/static/chunks/11rpr3..poyv8.js +0 -5
  126. package/.next/standalone/apps/web/.next/static/chunks/1200zkjn5n2w7.js +0 -1
  127. /package/.next/standalone/apps/web/.next/static/{otC3BXpS9D6HI8k0EQ2ZH → C1cjF-gU-snY_atxJbn1v}/_buildManifest.js +0 -0
  128. /package/.next/standalone/apps/web/.next/static/{otC3BXpS9D6HI8k0EQ2ZH → C1cjF-gU-snY_atxJbn1v}/_clientMiddlewareManifest.js +0 -0
  129. /package/.next/standalone/apps/web/.next/static/{otC3BXpS9D6HI8k0EQ2ZH → C1cjF-gU-snY_atxJbn1v}/_ssgManifest.js +0 -0
@@ -2,6 +2,6 @@ module.exports=[40006,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944
2
2
  flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer
3
3
  transition-colors
4
4
  ${c?"bg-accent":"hover:bg-accent"}
5
- `,style:{paddingLeft:`${16*e+8}px`},children:[o&&(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-xs",onClick:a=>{a.stopPropagation(),g&&g()},className:"size-4",children:d?(0,b.jsx)(l,{className:"w-3 h-3 text-muted-foreground"}):(0,b.jsx)(k.default,{className:"w-3 h-3 text-muted-foreground"})}),!o&&(0,b.jsx)("div",{className:"w-3"}),(0,b.jsx)("div",{className:"text-foreground",children:(()=>{switch(a.type){case"global":return(0,b.jsx)(h,{className:"w-4 h-4"});case"owner":return(0,b.jsx)(i,{className:"w-4 h-4"});case"repo":return(0,b.jsx)(j.GitBranch,{className:"w-4 h-4"})}})()}),(0,b.jsx)("span",{className:"text-sm text-foreground truncate",children:a.label})]})}function o({selectedNode:a,onNodeSelect:d,refreshKey:e}){let[g,h]=(0,c.useState)([]),[i,j]=(0,c.useState)(new Set),[k,l]=(0,c.useState)(!0);(0,c.useEffect)(()=>{let a=localStorage.getItem("tsunagi:env-tree-expanded");if(a)try{let b=JSON.parse(a);j(new Set(b))}catch(a){console.error("Failed to parse expanded owners:",a)}},[]),(0,c.useEffect)(()=>{localStorage.setItem("tsunagi:env-tree-expanded",JSON.stringify([...i]))},[i]),(0,c.useEffect)(()=>{(async()=>{l(!0);try{let a=await fetch((0,f.apiUrl)("/api/owners"));if(!a.ok)throw Error("Failed to fetch owners");let b=((await a.json()).data.owners||[]).map(a=>({id:`owner:${a.name}`,type:"owner",label:a.name,scope:"owner",owner:a.name,children:a.repositories.map(a=>({id:`repo:${a.owner}/${a.repo}`,type:"repo",label:a.repo,scope:"repo",owner:a.owner,repo:a.repo}))}));h([{id:"global",type:"global",label:"Global",scope:"global"},...b])}catch(a){console.error("Failed to load tree:",a)}finally{l(!1)}})()},[e]);let m=(c,e=0)=>{let f=a?.scope===c.scope&&a?.owner===c.owner&&a?.repo===c.repo,g=i.has(c.id);return(0,b.jsxs)("div",{children:[(0,b.jsx)(n,{node:c,isSelected:f,isExpanded:g,depth:e,onSelect:()=>{d({scope:c.scope,owner:c.owner,repo:c.repo,label:c.label})},onToggle:()=>{var a;return a=c.id,void j(b=>{let c=new Set(b);return c.has(a)?c.delete(a):c.add(a),c})}}),g&&c.children?.map(a=>m(a,e+1))]},c.id)};return k?(0,b.jsx)("div",{className:"p-4 text-muted-foreground text-sm",children:"Loading..."}):0===g.length?(0,b.jsx)("div",{className:"p-4 text-muted-foreground text-sm",children:"No repositories found"}):(0,b.jsx)("div",{className:"h-full overflow-y-auto",children:(0,b.jsx)("div",{className:"p-2",children:g.map(a=>m(a))})})}var p=a.i(15618),q=a.i(33508),r=a.i(33441),s=a.i(77156);let t=(0,g.default)("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);var u=a.i(81560),v=a.i(99464),w=a.i(28503);function x({variable:a,onToggle:d,onDelete:e,onUpdate:f,isDeletable:g=!0}){let[h,i]=(0,c.useState)(!1),[j,k]=(0,c.useState)(!1),[l,n]=(0,c.useState)(!1),[o,p]=(0,c.useState)(a.value),y=async b=>{k(!0);try{await d(a.key,b.target.checked)}finally{k(!1)}},z=async()=>{await e(a.key)},A=async()=>{try{await f(a.key,o),n(!1)}catch(a){console.error("Failed to update variable:",a),alert("Failed to update variable")}};return(0,b.jsxs)("div",{className:"border border-border rounded p-3 space-y-2",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-sm font-mono text-foreground",children:a.key}),!l&&(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,b.jsx)("input",{type:"checkbox",checked:a.enabled,onChange:y,disabled:j,className:"w-4 h-4 cursor-pointer"}),(0,b.jsx)("span",{className:"text-xs text-muted-foreground",children:"Enabled"})]}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>i(!h),title:h?"Hide value":"Show value",children:h?(0,b.jsx)(t,{className:"w-4 h-4 text-muted-foreground"}):(0,b.jsx)(s.Eye,{className:"w-4 h-4 text-muted-foreground"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>{n(!0),p(a.value)},title:"Edit",children:(0,b.jsx)(v.Pencil,{className:"w-4 h-4 text-muted-foreground"})}),g&&(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:z,title:"Delete",children:(0,b.jsx)(u.Trash2,{className:"w-4 h-4 text-destructive"})})]})]}),l?(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsx)(w.Input,{type:"password",value:o,onChange:a=>p(a.target.value),className:"w-full font-mono",autoFocus:!0}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{n(!1),p(a.value)},className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:A,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]}):(0,b.jsx)("div",{children:(0,b.jsx)(w.Input,{type:h?"text":"password",value:a.value,readOnly:!0,className:"w-full font-mono"})})]})}var y=a.i(67060);let z=["ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN"];function A({selectedNode:a}){let[d,e]=(0,c.useState)([]),[g,h]=(0,c.useState)(!0),[i,j]=(0,c.useState)(null),[k,l]=(0,c.useState)(!1),[n,o]=(0,c.useState)(""),[s,t]=(0,c.useState)(""),[u,v]=(0,c.useState)("");(0,c.useEffect)(()=>{(async()=>{h(!0),j(null);try{let b=new URLSearchParams({scope:a.scope});a.owner&&b.set("owner",a.owner),a.repo&&b.set("repo",a.repo);let c=await fetch((0,f.apiUrl)(`/api/env/list?${b}`));if(!c.ok)throw Error("Failed to fetch environment variables");let d=((await c.json()).data.envVars||[]).filter(a=>!z.includes(a.key));e(d)}catch(a){console.error("Failed to load environment variables:",a),j("Failed to load environment variables")}finally{h(!1)}})()},[a]);let B=async(b,c)=>{if("global"===a.scope&&!c&&("ANTHROPIC_API_KEY"===b||"CLAUDE_CODE_OAUTH_TOKEN"===b)&&!d.find(a=>a.key!==b&&("ANTHROPIC_API_KEY"===a.key||"CLAUDE_CODE_OAUTH_TOKEN"===a.key)&&a.enabled))return void alert("Cannot disable the last enabled Claude Token. Please add or enable another Claude Token first.");try{if(!(await fetch((0,f.apiUrl)("/api/env/toggle"),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,scope:a.scope,owner:a.owner,repo:a.repo,enabled:c})})).ok)throw Error("Failed to toggle environment variable");e(a=>a.map(a=>a.key===b?{...a,enabled:c}:a))}catch(a){console.error("Failed to toggle environment variable:",a),e(a=>a.map(a=>a.key===b?{...a,enabled:!c}:a))}},C=async b=>{if(confirm(`Delete ${b}?`))try{let c=new URLSearchParams({key:b,scope:a.scope});if(a.owner&&c.set("owner",a.owner),a.repo&&c.set("repo",a.repo),!(await fetch((0,f.apiUrl)(`/api/env?${c}`),{method:"DELETE"})).ok)throw Error("Failed to delete environment variable");e(a=>a.filter(a=>a.key!==b))}catch(a){console.error("Failed to delete environment variable:",a),alert("Failed to delete environment variable")}},D=async(b,c)=>{try{if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,value:c,scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to update environment variable");e(a=>a.map(a=>a.key===b?{...a,value:c}:a))}catch(a){throw console.error("Failed to update environment variable:",a),a}},E=async()=>{var b;if(v(""),!n.trim())return void v("Key is required");if(!s.trim())return void v("Value is required");if(b=n.trim(),/^[A-Z0-9_]+$/.test(b)?z.includes(b)?(v("Claude tokens should be added in the Tokens section"),!1):!d.some(a=>a.key===b)||(v(`Key "${b}" already exists in this scope`),!1):(v("Key must contain only uppercase letters, numbers, and underscores"),!1))try{if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n.trim(),value:s.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to add environment variable");let b=new URLSearchParams({scope:a.scope});a.owner&&b.set("owner",a.owner),a.repo&&b.set("repo",a.repo);let c=await fetch((0,f.apiUrl)(`/api/env/list?${b}`));if(c.ok){let a=((await c.json()).data.envVars||[]).filter(a=>!z.includes(a.key));e(a)}l(!1),o(""),t("")}catch(a){console.error("Failed to add environment variable:",a),v("Failed to add environment variable")}};return g?(0,b.jsx)("div",{className:"h-full flex items-center justify-center",children:(0,b.jsx)(y.LoadingSpinner,{size:"md",message:"Loading variables..."})}):i?(0,b.jsx)("div",{className:"h-full flex items-center justify-center",children:(0,b.jsx)("div",{className:"text-destructive text-sm",children:i})}):(0,b.jsxs)("div",{className:"h-full flex flex-col",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground",children:"Environment Variables"}),!k&&(0,b.jsxs)(m.Button,{size:"sm",onClick:()=>l(!0),className:"active:scale-95",children:[(0,b.jsx)(p.Plus,{className:"w-4 h-4"}),"Add Variable"]})]}),(0,b.jsxs)("div",{className:"flex-1 overflow-y-auto space-y-3",children:[k&&(0,b.jsxs)("div",{className:"border border-border rounded p-3 bg-accent space-y-2",children:[(0,b.jsx)("div",{className:"text-sm font-medium text-foreground",children:"New Variable"}),(0,b.jsx)(w.Input,{type:"text",value:n,onChange:a=>o(a.target.value.toUpperCase()),placeholder:"VARIABLE_NAME",className:"w-full font-mono",autoFocus:!0}),(0,b.jsx)(w.Input,{type:"password",value:s,onChange:a=>t(a.target.value),placeholder:"value",className:"w-full font-mono"}),u&&(0,b.jsx)("div",{className:"text-xs text-destructive",children:u}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{l(!1),o(""),t(""),v("")},className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:E,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]}),0!==d.length||k?d.map(a=>(0,b.jsx)(x,{variable:a,onToggle:B,onDelete:C,onUpdate:D,isDeletable:!0},a.key)):(0,b.jsx)("div",{className:"text-center text-muted-foreground text-sm py-4",children:"No environment variables"})]})]})}var B=a.i(92e3);let C=["ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN"],D={ANTHROPIC_API_KEY:"API Key",CLAUDE_CODE_OAUTH_TOKEN:"OAuth Token"};function E(a){return a.startsWith("sk-ant-api")?"ANTHROPIC_API_KEY":a.startsWith("sk-ant-oat")?"CLAUDE_CODE_OAUTH_TOKEN":null}function F({selectedNode:a,onboardingStatus:d,onSwitchToGlobal:e}){let[g,h]=(0,c.useState)([]),[i,j]=(0,c.useState)(!0),[k,l]=(0,c.useState)(null),[n,o]=(0,c.useState)(null),[x,z]=(0,c.useState)(""),[A,G]=(0,c.useState)(""),[H,I]=(0,c.useState)(null),[J,K]=(0,c.useState)({}),[L,M]=(0,c.useState)(!1),[N,O]=(0,c.useState)(""),[P,Q]=(0,c.useState)(""),[R,S]=(0,c.useState)(null);(0,c.useEffect)(()=>{T()},[a]);let T=async()=>{j(!0),l(null);try{let b=new URLSearchParams({scope:a.scope});a.owner&&b.set("owner",a.owner),a.repo&&b.set("repo",a.repo);let c=await fetch((0,f.apiUrl)(`/api/env/list?${b}`));if(!c.ok)throw Error("Failed to fetch tokens");let d=((await c.json()).data.envVars||[]).filter(a=>C.includes(a.key)).map(a=>({key:a.key,value:a.value,label:D[a.key]||a.key}));h(d)}catch(a){console.error("Failed to load tokens:",a),l("Failed to load tokens")}finally{j(!1)}},U=()=>{o(null),z(""),G(""),I(null)},V=async b=>{if(!x.trim())return void G("Token value is required");let c=E(x);if(!c)return void G("Invalid token format");try{if(c!==b){let d=new URLSearchParams({key:b,scope:a.scope});a.owner&&d.set("owner",a.owner),a.repo&&d.set("repo",a.repo),await fetch((0,f.apiUrl)(`/api/env?${d}`),{method:"DELETE"}),await fetch((0,f.apiUrl)("/api/env"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:c,value:x.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})}else if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,value:x.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to update token");await T(),o(null),z(""),G(""),I(null)}catch(a){console.error("Failed to update token:",a),G("Failed to update token")}},W=async()=>{if(!N.trim())return void Q("Token value is required");let b=E(N);if(!b)return void Q("Invalid token format");if(g.length>0)return void Q("Only one Claude token is allowed per scope. Please edit the existing token.");try{if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,value:N.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to add token");await T(),M(!1),O(""),S(null)}catch(a){console.error("Failed to add token:",a),Q("Failed to add token")}},X=async b=>{if(confirm("Are you sure you want to delete this token?"))try{let c=new URLSearchParams({key:b,scope:a.scope});if(a.owner&&c.set("owner",a.owner),a.repo&&c.set("repo",a.repo),!(await fetch((0,f.apiUrl)(`/api/env?${c}`),{method:"DELETE"})).ok)throw Error("Failed to delete token");await T()}catch(a){console.error("Failed to delete token:",a),alert("Failed to delete token")}};if(i)return(0,b.jsxs)("div",{className:"border-2 border-primary rounded-xl p-4 bg-card",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground mb-4",children:"Claude Tokens"}),(0,b.jsx)("div",{className:"flex items-center justify-center py-8",children:(0,b.jsx)(y.LoadingSpinner,{size:"sm",message:"Loading tokens..."})})]});if(k)return(0,b.jsxs)("div",{className:"border-2 border-primary rounded-xl p-4 bg-card",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground mb-4",children:"Claude Tokens"}),(0,b.jsx)("div",{className:"text-destructive text-sm",children:k})]});let Y=d&&!d.completed&&"global"!==a.scope;return(0,b.jsxs)("div",{className:"border-2 border-primary rounded-xl p-4 bg-card",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground",children:"Claude Tokens"}),!L&&0===g.length&&(0,b.jsxs)(m.Button,{size:"sm",onClick:()=>M(!0),className:"active:scale-95",children:[(0,b.jsx)(p.Plus,{className:"w-4 h-4"}),"Add Token"]})]}),Y&&(0,b.jsxs)("div",{className:"mb-4 border-2 border-warning bg-warning/10 rounded-xl p-3 flex items-start gap-3",children:[(0,b.jsx)(B.AlertCircle,{className:"w-5 h-5 text-warning flex-shrink-0 mt-0.5"}),(0,b.jsx)("div",{className:"flex-1",children:(0,b.jsx)("p",{className:"text-sm text-warning",children:"オンボーディングを完了するには、Globalスコープにトークンを追加してください"})}),e&&(0,b.jsx)(m.Button,{size:"sm",onClick:e,className:"bg-warning text-white hover:bg-warning/80 active:scale-95 whitespace-nowrap",children:"Switch to Global"})]}),(0,b.jsxs)("div",{className:"space-y-3",children:[L&&(0,b.jsxs)("div",{className:"border border-border rounded p-3 bg-accent",children:[(0,b.jsx)("div",{className:"text-sm font-medium text-foreground mb-2",children:"New Token"}),(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsx)(w.Input,{type:"password",value:N,onChange:a=>{var b;let c;return O(b=a.target.value),Q(""),void(S(c=E(b)),b&&!c&&Q("Invalid token format. Must start with sk-ant-api or sk-ant-oat"))},placeholder:"sk-ant-api... or sk-ant-oat...",className:"w-full font-mono",autoFocus:!0}),R&&!P&&(0,b.jsxs)("div",{className:"text-xs text-success",children:["→ Detected: ",D[R]]}),P&&(0,b.jsx)("div",{className:"text-xs text-destructive",children:P}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{M(!1),O(""),Q(""),S(null)},className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:W,disabled:!R||!!P,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]})]}),0!==g.length||L?g.map(c=>(0,b.jsx)("div",{className:"border border-border rounded p-3 space-y-2",children:n===c.key?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{className:"text-sm font-medium text-foreground mb-2",children:"Edit Token"}),(0,b.jsx)(w.Input,{type:"password",value:x,onChange:a=>{var b;let c;return z(b=a.target.value),G(""),void(I(c=E(b)),b&&!c&&G("Invalid token format. Must start with sk-ant-api or sk-ant-oat"))},placeholder:"sk-ant-api... or sk-ant-oat...",className:"w-full font-mono",autoFocus:!0}),H&&!A&&(0,b.jsxs)("div",{className:"text-xs text-success",children:["→ Detected: ",D[H]]}),A&&(0,b.jsx)("div",{className:"text-xs text-destructive",children:A}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:U,className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:()=>V(c.key),disabled:!H||!!A,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-sm font-medium text-foreground",children:c.label}),(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>K(a=>({...a,[c.key]:!a[c.key]})),title:J[c.key]?"Hide value":"Show value",children:J[c.key]?(0,b.jsx)(t,{className:"w-4 h-4 text-muted-foreground"}):(0,b.jsx)(s.Eye,{className:"w-4 h-4 text-muted-foreground"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>{o(c.key),z(""),G(""),I(null)},title:"Edit",children:(0,b.jsx)(v.Pencil,{className:"w-4 h-4 text-muted-foreground"})}),"global"!==a.scope&&(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>X(c.key),className:"hover:bg-destructive/10",title:"Delete",children:(0,b.jsx)(u.Trash2,{className:"w-4 h-4 text-destructive"})})]})]}),(0,b.jsx)(w.Input,{type:J[c.key]?"text":"password",value:c.value,readOnly:!0,className:"w-full font-mono"})]})},c.key)):(0,b.jsx)("div",{className:"text-center text-muted-foreground text-sm py-4",children:"No Claude tokens configured"})]})]})}let G=(0,g.default)("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]);var H=a.i(49594),I=a.i(90002);function J(){let[a,d]=(0,c.useState)([]),[e,g]=(0,c.useState)({}),[h,i]=(0,c.useState)(null),[j,k]=(0,c.useState)(!1),[n,o]=(0,c.useState)(!1),p=(0,c.useCallback)(async()=>{try{let[a,b]=await Promise.all([fetch((0,f.apiUrl)("/api/repos")).then(a=>a.json()),fetch((0,f.apiUrl)("/api/tasks")).then(a=>a.json())]);d(a.data??[]);let c={};for(let a of b.data?.tasks??[]){let b=`${a.owner}/${a.repo}`;c[b]=(c[b]??0)+1}g(c)}catch(a){console.error("Failed to load repositories:",a)}},[]);(0,c.useEffect)(()=>{p()},[p]);let q=async()=>{if(h){k(!0);try{if(!(await fetch((0,f.apiUrl)(`/api/repos/${h.owner}/${h.repo}`),{method:"DELETE"})).ok)throw Error("Failed to delete repository");await p()}catch(a){console.error("Failed to delete repository:",a)}finally{k(!1),i(null)}}},r=(0,c.useCallback)(async(b,c)=>{let e=b+c;if(e<0||e>=a.length)return;let g=[...a];[g[b],g[e]]=[g[e],g[b]],d(g.map((a,b)=>({...a,order:b}))),o(!0);try{if(!(await fetch((0,f.apiUrl)("/api/repos/reorder"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({repoIds:g.map(a=>a.id)})})).ok)throw Error("Failed to reorder repositories")}catch(a){console.error("Failed to reorder repositories:",a),await p()}finally{o(!1)}},[a,p]);return 0===a.length?(0,b.jsx)("div",{className:"text-sm text-muted-foreground",children:"No repositories cloned yet."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(I.ConfirmDialog,{open:null!==h,onOpenChange:a=>{a.open||i(null)},title:"Delete Repository",message:h?`Delete ${h.owner}/${h.repo}? This will also delete ${e[`${h.owner}/${h.repo}`]??0} associated task(s), all worktrees, and the bare repository. This action cannot be undone.`:"",confirmLabel:j?"Deleting...":"Delete",cancelLabel:"Cancel",onConfirm:q,variant:"danger"}),(0,b.jsx)("p",{className:"text-xs text-muted-foreground",children:"この並び順がトップページの列の並び順になります"}),(0,b.jsx)("div",{className:"space-y-2",children:a.map((c,d)=>{let f=`${c.owner}/${c.repo}`,g=(0,H.getRepoColor)(c.owner,c.repo),h=e[f]??0;return(0,b.jsxs)("div",{className:"flex items-center justify-between gap-2 rounded-md border border-border p-3",children:[(0,b.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,b.jsx)("span",{className:`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${g.bg} ${g.text}`,children:f}),(0,b.jsxs)("span",{className:"text-xs text-muted-foreground whitespace-nowrap",children:[h," task",1!==h?"s":""]})]}),(0,b.jsxs)("div",{className:"flex flex-shrink-0 items-center",children:[(0,b.jsx)(m.Button,{variant:"ghost",size:"icon",onClick:()=>r(d,-1),disabled:0===d||n,className:"text-muted-foreground",title:"Move up",children:(0,b.jsx)(G,{className:"size-4"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon",onClick:()=>r(d,1),disabled:d===a.length-1||n,className:"text-muted-foreground",title:"Move down",children:(0,b.jsx)(l,{className:"size-4"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon",onClick:()=>i(c),className:"text-muted-foreground hover:text-destructive",title:"Delete repository",children:(0,b.jsx)(u.Trash2,{className:"size-4"})})]})]},c.id)})})]})}var K=a.i(26807);function L({owner:a,repo:d,onDeleted:e}){let[g,h]=(0,c.useState)(!1),[i,j]=(0,c.useState)(""),[k,l]=(0,c.useState)(!1),n=`${a}/${d}`,o=i===n,p=async()=>{if(o){l(!0);try{if(!(await fetch((0,f.apiUrl)(`/api/repos/${a}/${d}`),{method:"DELETE"})).ok)throw Error("Failed to delete repository");e()}catch(a){console.error("Failed to delete repository:",a)}finally{l(!1),h(!1),j("")}}};return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"rounded-md border border-destructive/30 p-4 space-y-3",children:[(0,b.jsxs)("div",{className:"space-y-1",children:[(0,b.jsx)("h3",{className:"text-sm font-semibold text-destructive",children:"Remove Repository"}),(0,b.jsx)("p",{className:"text-xs text-muted-foreground",children:"Remove this repository and all associated data including tasks, worktrees, and environment variables. This action cannot be undone."})]}),(0,b.jsxs)(m.Button,{variant:"destructive",size:"sm",onClick:()=>h(!0),children:[(0,b.jsx)(u.Trash2,{className:"size-4"}),"Remove Repository"]})]}),(0,b.jsx)(K.Dialog,{open:g,onOpenChange:h,children:(0,b.jsxs)(K.DialogContent,{showCloseButton:!1,children:[(0,b.jsxs)(K.DialogHeader,{children:[(0,b.jsx)(K.DialogTitle,{children:"Remove Repository"}),(0,b.jsxs)(K.DialogDescription,{children:["This will permanently delete ",(0,b.jsx)("strong",{children:n})," and all associated tasks, worktrees, and environment variables."]})]}),(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsxs)("label",{className:"text-xs text-muted-foreground",children:["Type ",(0,b.jsx)("strong",{children:n})," to confirm"]}),(0,b.jsx)(w.Input,{value:i,onChange:a=>j(a.target.value),placeholder:n,autoComplete:"off"})]}),(0,b.jsxs)(K.DialogFooter,{children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{h(!1),j("")},disabled:k,children:"Cancel"}),(0,b.jsx)(m.Button,{variant:"destructive",size:"sm",onClick:p,disabled:!o||k,children:k?"Removing...":"Remove"})]})]})})]})}var M=a.i(67453),N=a.i(36620),O=a.i(96221),P=a.i(4975),Q=a.i(48124),R=a.i(92552),S=a.i(65025),T=a.i(97463),U=a.i(6828),V=a.i(56026);let W="tsunagi:voice-input-enabled",X={not_running:"停止中",installing_deps:"依存関係をインストール中...",downloading_model:"モデルをダウンロード中...",starting_server:"サーバーを起動中...",running:"実行中",running_external:"実行中 (tsunagi外で起動)",error:"エラー"},Y=["installing_deps","downloading_model","starting_server"],Z=["running","running_external"];function $(a){let b=a/0x40000000;return b>=.1?`${b.toFixed(2)} GB`:`${(a/1048576).toFixed(0)} MB`}function _(){let[a,d]=(0,c.useState)(!1),[e,g]=(0,c.useState)(!1),[h,i]=(0,c.useState)(null),[j,k]=(0,c.useState)(""),l=(0,c.useRef)(null),n=(0,c.useCallback)(a=>{d(a),localStorage.setItem(W,String(a))},[]),o=(0,c.useCallback)(a=>{k(a),localStorage.setItem(V.WHISPER_PROMPT_STORAGE_KEY,a)},[]),p=(0,c.useCallback)(async()=>{let a=await fetch((0,f.apiUrl)("/api/whisper/server/status")),b=await a.json();return i(b),b},[]);(0,c.useEffect)(()=>{d("true"===localStorage.getItem(W)),k(localStorage.getItem(V.WHISPER_PROMPT_STORAGE_KEY)??""),p()},[p]),(0,c.useEffect)(()=>{h&&Z.includes(h.step)&&!a&&(n(!0),U.toaster.create({type:"success",title:"音声入力が有効化されました"}))},[h,a,n]),(0,c.useEffect)(()=>(h&&Y.includes(h.step)&&!l.current&&(l.current=setInterval(()=>{p().then(a=>{!Y.includes(a.step)&&l.current&&(clearInterval(l.current),l.current=null)})},1e3)),()=>{l.current&&(clearInterval(l.current),l.current=null)}),[h,p]);let q=(0,c.useCallback)(()=>{p(),g(!0)},[p]),r=(0,c.useCallback)(async()=>{try{let a=await fetch((0,f.apiUrl)("/api/whisper/server/start"),{method:"POST"});if(!a.ok){let b=await a.json().catch(()=>null);throw Error(b?.error||`HTTPエラー: ${a.status}`)}i(await a.json())}catch(a){U.toaster.create({type:"error",title:"サーバーの起動に失敗しました",description:a instanceof Error?a.message:String(a)})}},[]),s=(0,c.useCallback)(async()=>{try{let a=await fetch((0,f.apiUrl)("/api/whisper/server/stop"),{method:"POST"});if(!a.ok){let b=await a.json().catch(()=>null);throw Error(b?.error||`HTTPエラー: ${a.status}`)}i(await a.json())}catch(a){U.toaster.create({type:"error",title:"サーバーの停止に失敗しました",description:a instanceof Error?a.message:String(a)})}},[]),t=(0,c.useCallback)(()=>{n(!1),h&&Z.includes(h.step)&&s()},[n,s,h]),u=h?.serverDir,v=h?.downloadProgress,w=v?v.downloadedBytes/v.totalBytes*100:0,x=null!==h,y=x&&Z.includes(h.step);return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsxs)("div",{className:"flex items-center gap-1",children:[(0,b.jsx)(R.CardTitle,{children:"音声入力 (実験的機能)"}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-sm",onClick:q,title:"音声入力について",children:(0,b.jsx)(N.CircleHelp,{})})]}),(0,b.jsx)(R.CardDescription,{children:"ローカルで動作するWhisperを使って音声入力を行います。下記のローカルLLMも有効にすると、 文字起こし結果がLLMで自動整形されます(無効時は文字起こし結果をそのまま使用)。"})]}),(0,b.jsx)(R.CardContent,{className:"flex flex-col gap-3",children:a?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[x?y?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"音声入力: 有効"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-warning",children:[(0,b.jsx)(B.AlertCircle,{className:"size-4"}),"音声入力: 有効化済み(サーバー停止中)"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"状態を確認中..."]}),h&&(0,b.jsxs)("span",{className:"text-xs/relaxed text-muted-foreground",children:["(",X[h.step],")"]}),x&&!y&&(0,b.jsxs)(m.Button,{size:"default",onClick:q,children:[(0,b.jsx)(P.Mic,{}),"サーバーを起動"]}),(0,b.jsx)(m.Button,{size:"default",variant:"outline",onClick:t,children:"無効にする"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"文字起こしプロンプト (任意)"}),(0,b.jsx)(T.Textarea,{value:j,onChange:a=>o(a.target.value),placeholder:"例: 誤字、句読点、音声入力、Whisper、固有名詞や専門用語など",className:"min-h-16 text-xs"}),(0,b.jsx)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:"よく使う単語(固有名詞・専門用語・同音異義語で誤変換されやすい単語など)を列挙すると、 Whisperがその表記を優先しやすくなり誤変換が減ります。文章でなく単語の羅列でも構いません。空でも可。"})]})]}):(0,b.jsxs)(m.Button,{size:"default",onClick:q,children:[(0,b.jsx)(P.Mic,{}),"音声入力を有効化する"]})}),(0,b.jsx)(I.Dialog,{open:e,onOpenChange:({open:a})=>g(a),title:"音声入力について",maxWidth:"2xl",children:(0,b.jsxs)("div",{className:"space-y-4 text-sm",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"実験的機能です"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"音声入力はローカルで動作するWhisper (mlx-whisper) を利用します。精度・速度は環境に依存し、今後変更される可能性があります。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"対応環境"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"Apple Silicon Mac (M1/M2/M3/M4) のみ対応。Windows/Linuxでは利用できません。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"必要なもの(事前に手動でインストール)"}),(0,b.jsx)("ul",{className:"list-disc pl-5 text-muted-foreground",children:(0,b.jsx)("li",{children:"Python 3.9以降(Xcode Command Line Tools または Homebrew経由で入手可能)"})})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"mb-1 font-medium text-foreground",children:"セットアップ・起動"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"下のボタンから、依存関係のインストール・モデルのダウンロード・サーバー起動まで自動で行われます(初回は数分かかります)。"}),h&&!u&&(0,b.jsx)("p",{className:"mt-1 text-destructive",children:"whisper-serverが見つかりませんでした。インストールが壊れている可能性があります。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"mb-1 font-medium text-foreground",children:"アンインストール"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:["音声入力のためにダウンロードされるもの(Pythonの依存関係・Whisperモデル、合計約2.6GB)は全て",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"~/.tsunagi/whisper"}),"に保存されます。不要になった場合はこのディレクトリを削除するだけで、関連リソースを完全に削除できます。"]})]}),(0,b.jsxs)("div",{className:"border-t border-border pt-4",children:[(!h||"not_running"===h.step||"error"===h.step)&&(0,b.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void r(),disabled:!h,children:[h?(0,b.jsx)(P.Mic,{}):(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"Whisperサーバーを起動"]}),h?.step==="error"&&h.error&&(0,b.jsx)("p",{className:"text-xs/relaxed text-destructive",children:h.error})]}),h?.step==="installing_deps"&&(0,b.jsxs)(m.Button,{size:"default",disabled:!0,children:[(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"依存関係をインストール中... (数分かかる場合があります)"]}),h?.step==="downloading_model"&&(0,b.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 text-xs/relaxed text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"モデルをダウンロード中..."]}),v&&(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(S.Progress,{value:w}),(0,b.jsxs)("p",{className:"text-xs/relaxed text-muted-foreground",children:[$(v.downloadedBytes)," / ",$(v.totalBytes)," (",w.toFixed(0),"%) ・ ",function(a){if(null===a)return"残り時間を計算中...";if(a<60)return`残り約${a}秒`;let b=Math.floor(a/60);return`残り約${b}分${a%60}秒`}(v.etaSeconds)]})]})]}),h?.step==="starting_server"&&(0,b.jsxs)(m.Button,{size:"default",disabled:!0,children:[(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"サーバーを起動中..."]}),h&&Z.includes(h.step)&&(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"サーバーは起動しています"]}),(0,b.jsxs)(m.Button,{size:"default",variant:"outline",onClick:()=>void s(),children:[(0,b.jsx)(Q.Square,{}),"サーバーを停止"]})]})]})]})})]})}var aa=a.i(19768),ab=a.i(52495),ac=a.i(69520),ad=a.i(83604),ad=ad,ae=a.i(1464),af=a.i(72047);let ag="ollama-models";function ah(){let{settings:a,setSettings:d}=(0,af.useOllamaSettings)(),[e,g]=(0,c.useState)(null),[i,j]=(0,c.useState)(!1),[k,l]=(0,c.useState)(!1),[n,o]=(0,c.useState)([]),[p,q]=(0,c.useState)(!1),[r,s]=(0,c.useState)(null),[t,u]=(0,c.useState)(null),[v,x]=(0,c.useState)(!1),[y,z]=(0,c.useState)(null);(0,c.useEffect)(()=>{var b;a&&g({baseUrl:(b=a).baseUrl,model:b.model,contextTokens:String(b.contextTokens),extraEnvText:Object.entries(b.extraEnv).map(([a,b])=>`${a}=${b}`).join("\n")})},[a]);let A=(0,c.useCallback)(async a=>{j(!0);try{let b=await fetch((0,f.apiUrl)("/api/settings/ollama"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)}),c=await b.json().catch(()=>null);if(!b.ok||!c?.data)throw Error(c?.error||`HTTPエラー: ${b.status}`);return d(c.data),!0}catch(a){return U.toaster.create({type:"error",title:"Ollama の設定を保存できませんでした",description:a instanceof Error?a.message:String(a)}),!1}finally{j(!1)}},[d]),B=(0,c.useCallback)(async a=>{q(!0),s(null);try{let b=await fetch((0,f.apiUrl)(`/api/settings/ollama/models?baseUrl=${encodeURIComponent(a)}`)),c=await b.json().catch(()=>null);if(!b.ok||!c?.data)throw Error(c?.error||`HTTPエラー: ${b.status}`);o(c.data.models)}catch(a){o([]),s(a instanceof Error?a.message:String(a))}finally{q(!1)}},[]),C=(0,c.useCallback)(async a=>{x(!0),z(null);try{let b=await fetch((0,f.apiUrl)(`/api/settings/ollama/account?baseUrl=${encodeURIComponent(a)}`)),c=await b.json().catch(()=>null);if(!b.ok||!c?.data)throw Error(c?.error||`HTTPエラー: ${b.status}`);u(c.data)}catch(a){u(null),z(a instanceof Error?a.message:String(a))}finally{x(!1)}},[]),D=a?.enabled===!0,E=a?.baseUrl;(0,c.useEffect)(()=>{D&&E&&(B(E),C(E))},[D,E,B,C]);let F=(0,c.useCallback)(async()=>{a&&await A({...a,enabled:!0})&&U.toaster.create({type:"success",title:"Ollama を有効化しました"})},[a,A]),G=(0,c.useCallback)(()=>{a&&A({...a,enabled:!1})},[a,A]),H=(0,c.useCallback)(async()=>{!e||await A({enabled:!0,baseUrl:e.baseUrl,model:e.model,contextTokens:Number(e.contextTokens),extraEnv:function(a){let b={};for(let c of a.split("\n")){let a=c.trim();if(!a||a.startsWith("#"))continue;let d=a.indexOf("=");d<=0||(b[a.slice(0,d).trim()]=a.slice(d+1).trim())}return b}(e.extraEnvText)})&&U.toaster.create({type:"success",title:"Ollama の設定を保存しました"})},[e,A]),J=a=>g(b=>b?{...b,...a}:b);return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsxs)("div",{className:"flex items-center gap-1",children:[(0,b.jsx)(R.CardTitle,{children:"Ollama (実験的機能)"}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-sm",onClick:()=>l(!0),title:"Ollama について",children:(0,b.jsx)(N.CircleHelp,{})})]}),(0,b.jsxs)(R.CardDescription,{children:["Ollama のローカルLLMで Claude Code を起動できるようにします。",(0,b.jsx)("strong",{className:"font-medium text-foreground",children:"有効にすると、タスク詳細画面に Ollama タブの作成ボタンが表示されます"}),"。Ollama のインストール・モデルの pull・起動はご自身で行ってください。"]})]}),(0,b.jsx)(R.CardContent,{className:"flex flex-col gap-3",children:a&&e?D?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"Ollama: 有効"]}),!a.model&&(0,b.jsx)("span",{className:"text-xs text-warning",children:"モデルを設定すると利用できます"}),(0,b.jsx)(m.Button,{size:"default",variant:"outline",onClick:G,disabled:i,children:"無効にする"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"Base URL"}),(0,b.jsx)(w.Input,{value:e.baseUrl,onChange:a=>J({baseUrl:a.target.value}),placeholder:"http://localhost:11434"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"モデル"}),(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)(w.Input,{value:e.model,onChange:a=>J({model:a.target.value}),placeholder:"qwen3.8:27b",list:ag}),(0,b.jsx)("datalist",{id:ag,children:n.map(a=>(0,b.jsx)("option",{value:a},a))}),(0,b.jsx)(m.Button,{variant:"outline",size:"icon",onClick:()=>void B(e.baseUrl),disabled:p,title:"pull 済みのモデル一覧を取得",children:(0,b.jsx)(ac.RefreshCw,{className:p?"animate-spin":void 0})})]}),r?(0,b.jsx)("p",{className:"mt-1 text-[0.65rem] text-destructive",children:r}):(0,b.jsxs)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:["pull 済みのモデルは候補から選べます(",n.length,"件)。"]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"WebSearch"}),(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[v?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"確認中..."]}):t?.signedIn?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(h,{className:"size-4"}),"利用可能(ollama.com: ",t.name,")"]}):t?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-warning",children:[(0,b.jsx)(ad.default,{className:"size-4"}),"ollama.com 未サインイン"]}),t.signinUrl&&(0,b.jsxs)("a",{href:t.signinUrl,target:"_blank",rel:"noreferrer",className:(0,m.buttonVariants)({variant:"outline",size:"sm"}),children:[(0,b.jsx)(ab.ExternalLink,{}),"サインイン"]})]}):(0,b.jsx)("span",{className:"text-xs text-destructive",children:y}),(0,b.jsx)(m.Button,{variant:"outline",size:"icon",onClick:()=>void C(e.baseUrl),disabled:v,title:"サインイン状態を再確認",children:(0,b.jsx)(ac.RefreshCw,{className:v?"animate-spin":void 0})})]}),(0,b.jsxs)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:["Ollama が ollama.com の Web 検索 API で代行します。Ollama を動かしているマシンで"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"ollama signin"})," ","を実行してください(無料アカウントで可、検索クエリは ollama.com に送信されます)。"]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"コンテキスト長 (tokens)"}),(0,b.jsx)(w.Input,{type:"number",min:1,value:e.contextTokens,onChange:a=>J({contextTokens:a.target.value})}),(0,b.jsx)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:"Ollama 側のコンテキスト長と同じ値にしてください。Claude Code の自動compactの判定に使います(64k以上を推奨)。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"追加の環境変数 (任意)"}),(0,b.jsx)(T.Textarea,{value:e.extraEnvText,onChange:a=>J({extraEnvText:a.target.value}),placeholder:"KEY=VALUE(1行に1つ)",className:"min-h-16 font-mono text-xs"}),(0,b.jsx)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:"Ollama タブにのみ適用されます。同名の既定値より優先されます。"})]}),(0,b.jsx)("div",{children:(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void H(),disabled:i,children:[i&&(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"保存"]})})]}):(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void F(),disabled:i,children:[(0,b.jsx)(ae.OllamaIcon,{className:"size-4"}),"Ollama を有効化する"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"読み込み中..."]})}),(0,b.jsx)(I.Dialog,{open:k,onOpenChange:({open:a})=>l(a),title:"Ollama について",maxWidth:"2xl",children:(0,b.jsxs)("div",{className:"space-y-4 text-sm",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"実験的機能です"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"Claude Code の接続先を Ollama の Anthropic 互換 API (Ollama v0.14.0以降) に切り替えて起動します。Anthropic はClaude以外のモデルへの接続をサポートしていないため、動作は保証されません。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"WebSearch / WebFetch"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:["WebSearch は Ollama が ollama.com の Web 検索 API で代行するため、Ollama を動かしているマシンで ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"ollama signin"})," ","が必要です(未サインインだと「Web search error: unavailable」になります)。WebFetch はサインイン不要で、取得したページの要約も Ollama のモデルで行います。"]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"mb-1 font-medium text-foreground",children:"セットアップ"}),(0,b.jsxs)("ol",{className:"list-decimal space-y-1 pl-5 text-muted-foreground",children:[(0,b.jsxs)("li",{children:["Ollama をインストールする(",(0,b.jsx)("a",{href:"https://ollama.com/download",target:"_blank",rel:"noreferrer",className:"underline",children:"ollama.com"}),"のアプリ、または ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"brew install ollama"}),")"]}),(0,b.jsxs)("li",{children:["モデルを pull する(例:"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"ollama pull qwen3.8:27b"}),")"]}),(0,b.jsxs)("li",{children:["コンテキスト長を 64k 以上にする。アプリは設定画面のスライダー、CLI は"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"OLLAMA_CONTEXT_LENGTH=65536 ollama serve"})," ","で起動する。既定値(VRAM 24GiB 未満は 4k)のままだと tool call が壊れます"]}),(0,b.jsx)("li",{children:"ここで有効化し、モデルとコンテキスト長を設定して保存する"})]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"Docker で tsunagi を動かしている場合"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:["Base URL は"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"http://host.docker.internal:11434"})," ","を指定してください。"]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"注意"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:[(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"~/.claude/settings.json"})," の"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"env"})," に"," ",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"ANTHROPIC_*"})," ","を設定している場合、そちらが優先され Ollama に接続されません。設定の変更は、新しく作成した Ollama タブから反映されます。"]})]})]})})]})}var ai=a.i(78512);a.s(["default",0,function(){let a=(0,d.useRouter)();(0,ai.useDocumentTitle)("settings");let g=()=>({scope:"global",label:"Global"}),[h,i]=(0,c.useState)(null),[j,k]=(0,c.useState)(0),[l,n]=(0,c.useState)({completed:!0,hasGlobalToken:!0});return(0,c.useEffect)(()=>{fetch((0,f.apiUrl)("/api/onboarding/status")).then(a=>a.json()).then(a=>{let b=a.data;n(b),b.completed||b.hasGlobalToken?i(g()):i({scope:"global",label:"Global"})}).catch(a=>{console.error("Failed to fetch onboarding status:",a),i(g())})},[]),(0,c.useEffect)(()=>{h&&localStorage.setItem("tsunagi:env-selected-node",JSON.stringify(h))},[h]),(0,b.jsxs)("div",{className:"h-screen flex flex-col bg-background",children:[(0,b.jsx)("div",{className:"sticky top-0 z-50 p-4 border-b border-border bg-card",children:(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsxs)(m.Button,{variant:"ghost",onClick:()=>a.push("/"),className:"text-primary font-medium hover:bg-primary/10 hover:text-foreground",children:[(0,b.jsx)(e.ArrowLeft,{className:"w-4 h-4"}),"Back to Board"]}),(0,b.jsx)("h1",{className:"text-xl font-bold text-foreground absolute left-1/2 -translate-x-1/2",children:"Settings"})]})}),(0,b.jsxs)("div",{className:"flex-1 flex min-h-0",children:[(0,b.jsx)("div",{className:"w-64 border-r border-border bg-card",children:(0,b.jsx)(o,{selectedNode:h,onNodeSelect:a=>{i(a)},refreshKey:j})}),(0,b.jsx)("div",{className:"flex-1 bg-card p-4 overflow-y-auto",children:h?(0,b.jsxs)("div",{className:"space-y-6",children:[(0,b.jsx)(F,{selectedNode:h,onboardingStatus:l,onSwitchToGlobal:()=>{i({scope:"global",label:"Global"})}}),(0,b.jsx)(A,{selectedNode:h}),"global"===h.scope&&(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-foreground",children:"Repositories"}),(0,b.jsx)(J,{})]}),"global"===h.scope&&(0,b.jsx)(_,{}),"global"===h.scope&&(0,b.jsx)(aa.LocalLlmSection,{}),"global"===h.scope&&(0,b.jsx)(ah,{}),"repo"===h.scope&&h.owner&&h.repo&&(0,b.jsx)(L,{owner:h.owner,repo:h.repo,onDeleted:()=>{i({scope:"global",label:"Global"}),k(a=>a+1)}})]}):(0,b.jsx)("div",{className:"h-full flex items-center justify-center text-muted-foreground text-sm",children:"Select a node from the left panel"})})]})]})}],40006)}];
5
+ `,style:{paddingLeft:`${16*e+8}px`},children:[o&&(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-xs",onClick:a=>{a.stopPropagation(),g&&g()},className:"size-4",children:d?(0,b.jsx)(l,{className:"w-3 h-3 text-muted-foreground"}):(0,b.jsx)(k.default,{className:"w-3 h-3 text-muted-foreground"})}),!o&&(0,b.jsx)("div",{className:"w-3"}),(0,b.jsx)("div",{className:"text-foreground",children:(()=>{switch(a.type){case"global":return(0,b.jsx)(h,{className:"w-4 h-4"});case"owner":return(0,b.jsx)(i,{className:"w-4 h-4"});case"repo":return(0,b.jsx)(j.GitBranch,{className:"w-4 h-4"})}})()}),(0,b.jsx)("span",{className:"text-sm text-foreground truncate",children:a.label})]})}function o({selectedNode:a,onNodeSelect:d,refreshKey:e}){let[g,h]=(0,c.useState)([]),[i,j]=(0,c.useState)(new Set),[k,l]=(0,c.useState)(!0);(0,c.useEffect)(()=>{let a=localStorage.getItem("tsunagi:env-tree-expanded");if(a)try{let b=JSON.parse(a);j(new Set(b))}catch(a){console.error("Failed to parse expanded owners:",a)}},[]),(0,c.useEffect)(()=>{localStorage.setItem("tsunagi:env-tree-expanded",JSON.stringify([...i]))},[i]),(0,c.useEffect)(()=>{(async()=>{l(!0);try{let a=await fetch((0,f.apiUrl)("/api/owners"));if(!a.ok)throw Error("Failed to fetch owners");let b=((await a.json()).data.owners||[]).map(a=>({id:`owner:${a.name}`,type:"owner",label:a.name,scope:"owner",owner:a.name,children:a.repositories.map(a=>({id:`repo:${a.owner}/${a.repo}`,type:"repo",label:a.repo,scope:"repo",owner:a.owner,repo:a.repo}))}));h([{id:"global",type:"global",label:"Global",scope:"global"},...b])}catch(a){console.error("Failed to load tree:",a)}finally{l(!1)}})()},[e]);let m=(c,e=0)=>{let f=a?.scope===c.scope&&a?.owner===c.owner&&a?.repo===c.repo,g=i.has(c.id);return(0,b.jsxs)("div",{children:[(0,b.jsx)(n,{node:c,isSelected:f,isExpanded:g,depth:e,onSelect:()=>{d({scope:c.scope,owner:c.owner,repo:c.repo,label:c.label})},onToggle:()=>{var a;return a=c.id,void j(b=>{let c=new Set(b);return c.has(a)?c.delete(a):c.add(a),c})}}),g&&c.children?.map(a=>m(a,e+1))]},c.id)};return k?(0,b.jsx)("div",{className:"p-4 text-muted-foreground text-sm",children:"Loading..."}):0===g.length?(0,b.jsx)("div",{className:"p-4 text-muted-foreground text-sm",children:"No repositories found"}):(0,b.jsx)("div",{className:"h-full overflow-y-auto",children:(0,b.jsx)("div",{className:"p-2",children:g.map(a=>m(a))})})}var p=a.i(15618),q=a.i(33508),r=a.i(33441),s=a.i(77156);let t=(0,g.default)("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);var u=a.i(81560),v=a.i(99464),w=a.i(28503);function x({variable:a,onToggle:d,onDelete:e,onUpdate:f,isDeletable:g=!0}){let[h,i]=(0,c.useState)(!1),[j,k]=(0,c.useState)(!1),[l,n]=(0,c.useState)(!1),[o,p]=(0,c.useState)(a.value),y=async b=>{k(!0);try{await d(a.key,b.target.checked)}finally{k(!1)}},z=async()=>{await e(a.key)},A=async()=>{try{await f(a.key,o),n(!1)}catch(a){console.error("Failed to update variable:",a),alert("Failed to update variable")}};return(0,b.jsxs)("div",{className:"border border-border rounded p-3 space-y-2",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-sm font-mono text-foreground",children:a.key}),!l&&(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,b.jsx)("input",{type:"checkbox",checked:a.enabled,onChange:y,disabled:j,className:"w-4 h-4 cursor-pointer"}),(0,b.jsx)("span",{className:"text-xs text-muted-foreground",children:"Enabled"})]}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>i(!h),title:h?"Hide value":"Show value",children:h?(0,b.jsx)(t,{className:"w-4 h-4 text-muted-foreground"}):(0,b.jsx)(s.Eye,{className:"w-4 h-4 text-muted-foreground"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>{n(!0),p(a.value)},title:"Edit",children:(0,b.jsx)(v.Pencil,{className:"w-4 h-4 text-muted-foreground"})}),g&&(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:z,title:"Delete",children:(0,b.jsx)(u.Trash2,{className:"w-4 h-4 text-destructive"})})]})]}),l?(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsx)(w.Input,{type:"password",value:o,onChange:a=>p(a.target.value),className:"w-full font-mono",autoFocus:!0}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{n(!1),p(a.value)},className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:A,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]}):(0,b.jsx)("div",{children:(0,b.jsx)(w.Input,{type:h?"text":"password",value:a.value,readOnly:!0,className:"w-full font-mono"})})]})}var y=a.i(67060);let z=["ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN"];function A({selectedNode:a}){let[d,e]=(0,c.useState)([]),[g,h]=(0,c.useState)(!0),[i,j]=(0,c.useState)(null),[k,l]=(0,c.useState)(!1),[n,o]=(0,c.useState)(""),[s,t]=(0,c.useState)(""),[u,v]=(0,c.useState)("");(0,c.useEffect)(()=>{(async()=>{h(!0),j(null);try{let b=new URLSearchParams({scope:a.scope});a.owner&&b.set("owner",a.owner),a.repo&&b.set("repo",a.repo);let c=await fetch((0,f.apiUrl)(`/api/env/list?${b}`));if(!c.ok)throw Error("Failed to fetch environment variables");let d=((await c.json()).data.envVars||[]).filter(a=>!z.includes(a.key));e(d)}catch(a){console.error("Failed to load environment variables:",a),j("Failed to load environment variables")}finally{h(!1)}})()},[a]);let B=async(b,c)=>{if("global"===a.scope&&!c&&("ANTHROPIC_API_KEY"===b||"CLAUDE_CODE_OAUTH_TOKEN"===b)&&!d.find(a=>a.key!==b&&("ANTHROPIC_API_KEY"===a.key||"CLAUDE_CODE_OAUTH_TOKEN"===a.key)&&a.enabled))return void alert("Cannot disable the last enabled Claude Token. Please add or enable another Claude Token first.");try{if(!(await fetch((0,f.apiUrl)("/api/env/toggle"),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,scope:a.scope,owner:a.owner,repo:a.repo,enabled:c})})).ok)throw Error("Failed to toggle environment variable");e(a=>a.map(a=>a.key===b?{...a,enabled:c}:a))}catch(a){console.error("Failed to toggle environment variable:",a),e(a=>a.map(a=>a.key===b?{...a,enabled:!c}:a))}},C=async b=>{if(confirm(`Delete ${b}?`))try{let c=new URLSearchParams({key:b,scope:a.scope});if(a.owner&&c.set("owner",a.owner),a.repo&&c.set("repo",a.repo),!(await fetch((0,f.apiUrl)(`/api/env?${c}`),{method:"DELETE"})).ok)throw Error("Failed to delete environment variable");e(a=>a.filter(a=>a.key!==b))}catch(a){console.error("Failed to delete environment variable:",a),alert("Failed to delete environment variable")}},D=async(b,c)=>{try{if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,value:c,scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to update environment variable");e(a=>a.map(a=>a.key===b?{...a,value:c}:a))}catch(a){throw console.error("Failed to update environment variable:",a),a}},E=async()=>{var b;if(v(""),!n.trim())return void v("Key is required");if(!s.trim())return void v("Value is required");if(b=n.trim(),/^[A-Z0-9_]+$/.test(b)?z.includes(b)?(v("Claude tokens should be added in the Tokens section"),!1):!d.some(a=>a.key===b)||(v(`Key "${b}" already exists in this scope`),!1):(v("Key must contain only uppercase letters, numbers, and underscores"),!1))try{if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n.trim(),value:s.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to add environment variable");let b=new URLSearchParams({scope:a.scope});a.owner&&b.set("owner",a.owner),a.repo&&b.set("repo",a.repo);let c=await fetch((0,f.apiUrl)(`/api/env/list?${b}`));if(c.ok){let a=((await c.json()).data.envVars||[]).filter(a=>!z.includes(a.key));e(a)}l(!1),o(""),t("")}catch(a){console.error("Failed to add environment variable:",a),v("Failed to add environment variable")}};return g?(0,b.jsx)("div",{className:"h-full flex items-center justify-center",children:(0,b.jsx)(y.LoadingSpinner,{size:"md",message:"Loading variables..."})}):i?(0,b.jsx)("div",{className:"h-full flex items-center justify-center",children:(0,b.jsx)("div",{className:"text-destructive text-sm",children:i})}):(0,b.jsxs)("div",{className:"h-full flex flex-col",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground",children:"Environment Variables"}),!k&&(0,b.jsxs)(m.Button,{size:"sm",onClick:()=>l(!0),className:"active:scale-95",children:[(0,b.jsx)(p.Plus,{className:"w-4 h-4"}),"Add Variable"]})]}),(0,b.jsxs)("div",{className:"flex-1 overflow-y-auto space-y-3",children:[k&&(0,b.jsxs)("div",{className:"border border-border rounded p-3 bg-accent space-y-2",children:[(0,b.jsx)("div",{className:"text-sm font-medium text-foreground",children:"New Variable"}),(0,b.jsx)(w.Input,{type:"text",value:n,onChange:a=>o(a.target.value.toUpperCase()),placeholder:"VARIABLE_NAME",className:"w-full font-mono",autoFocus:!0}),(0,b.jsx)(w.Input,{type:"password",value:s,onChange:a=>t(a.target.value),placeholder:"value",className:"w-full font-mono"}),u&&(0,b.jsx)("div",{className:"text-xs text-destructive",children:u}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{l(!1),o(""),t(""),v("")},className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:E,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]}),0!==d.length||k?d.map(a=>(0,b.jsx)(x,{variable:a,onToggle:B,onDelete:C,onUpdate:D,isDeletable:!0},a.key)):(0,b.jsx)("div",{className:"text-center text-muted-foreground text-sm py-4",children:"No environment variables"})]})]})}var B=a.i(92e3);let C=["ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN"],D={ANTHROPIC_API_KEY:"API Key",CLAUDE_CODE_OAUTH_TOKEN:"OAuth Token"};function E(a){return a.startsWith("sk-ant-api")?"ANTHROPIC_API_KEY":a.startsWith("sk-ant-oat")?"CLAUDE_CODE_OAUTH_TOKEN":null}function F({selectedNode:a,onboardingStatus:d,onSwitchToGlobal:e}){let[g,h]=(0,c.useState)([]),[i,j]=(0,c.useState)(!0),[k,l]=(0,c.useState)(null),[n,o]=(0,c.useState)(null),[x,z]=(0,c.useState)(""),[A,G]=(0,c.useState)(""),[H,I]=(0,c.useState)(null),[J,K]=(0,c.useState)({}),[L,M]=(0,c.useState)(!1),[N,O]=(0,c.useState)(""),[P,Q]=(0,c.useState)(""),[R,S]=(0,c.useState)(null);(0,c.useEffect)(()=>{T()},[a]);let T=async()=>{j(!0),l(null);try{let b=new URLSearchParams({scope:a.scope});a.owner&&b.set("owner",a.owner),a.repo&&b.set("repo",a.repo);let c=await fetch((0,f.apiUrl)(`/api/env/list?${b}`));if(!c.ok)throw Error("Failed to fetch tokens");let d=((await c.json()).data.envVars||[]).filter(a=>C.includes(a.key)).map(a=>({key:a.key,value:a.value,label:D[a.key]||a.key}));h(d)}catch(a){console.error("Failed to load tokens:",a),l("Failed to load tokens")}finally{j(!1)}},U=()=>{o(null),z(""),G(""),I(null)},V=async b=>{if(!x.trim())return void G("Token value is required");let c=E(x);if(!c)return void G("Invalid token format");try{if(c!==b){let d=new URLSearchParams({key:b,scope:a.scope});a.owner&&d.set("owner",a.owner),a.repo&&d.set("repo",a.repo),await fetch((0,f.apiUrl)(`/api/env?${d}`),{method:"DELETE"}),await fetch((0,f.apiUrl)("/api/env"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:c,value:x.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})}else if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,value:x.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to update token");await T(),o(null),z(""),G(""),I(null)}catch(a){console.error("Failed to update token:",a),G("Failed to update token")}},W=async()=>{if(!N.trim())return void Q("Token value is required");let b=E(N);if(!b)return void Q("Invalid token format");if(g.length>0)return void Q("Only one Claude token is allowed per scope. Please edit the existing token.");try{if(!(await fetch((0,f.apiUrl)("/api/env"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:b,value:N.trim(),scope:a.scope,owner:a.owner,repo:a.repo})})).ok)throw Error("Failed to add token");await T(),M(!1),O(""),S(null)}catch(a){console.error("Failed to add token:",a),Q("Failed to add token")}},X=async b=>{if(confirm("Are you sure you want to delete this token?"))try{let c=new URLSearchParams({key:b,scope:a.scope});if(a.owner&&c.set("owner",a.owner),a.repo&&c.set("repo",a.repo),!(await fetch((0,f.apiUrl)(`/api/env?${c}`),{method:"DELETE"})).ok)throw Error("Failed to delete token");await T()}catch(a){console.error("Failed to delete token:",a),alert("Failed to delete token")}};if(i)return(0,b.jsxs)("div",{className:"border-2 border-primary rounded-xl p-4 bg-card",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground mb-4",children:"Claude Tokens"}),(0,b.jsx)("div",{className:"flex items-center justify-center py-8",children:(0,b.jsx)(y.LoadingSpinner,{size:"sm",message:"Loading tokens..."})})]});if(k)return(0,b.jsxs)("div",{className:"border-2 border-primary rounded-xl p-4 bg-card",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground mb-4",children:"Claude Tokens"}),(0,b.jsx)("div",{className:"text-destructive text-sm",children:k})]});let Y=d&&!d.completed&&"global"!==a.scope;return(0,b.jsxs)("div",{className:"border-2 border-primary rounded-xl p-4 bg-card",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,b.jsx)("h2",{className:"text-lg font-bold text-foreground",children:"Claude Tokens"}),!L&&0===g.length&&(0,b.jsxs)(m.Button,{size:"sm",onClick:()=>M(!0),className:"active:scale-95",children:[(0,b.jsx)(p.Plus,{className:"w-4 h-4"}),"Add Token"]})]}),Y&&(0,b.jsxs)("div",{className:"mb-4 border-2 border-warning bg-warning/10 rounded-xl p-3 flex items-start gap-3",children:[(0,b.jsx)(B.AlertCircle,{className:"w-5 h-5 text-warning flex-shrink-0 mt-0.5"}),(0,b.jsx)("div",{className:"flex-1",children:(0,b.jsx)("p",{className:"text-sm text-warning",children:"オンボーディングを完了するには、Globalスコープにトークンを追加してください"})}),e&&(0,b.jsx)(m.Button,{size:"sm",onClick:e,className:"bg-warning text-white hover:bg-warning/80 active:scale-95 whitespace-nowrap",children:"Switch to Global"})]}),(0,b.jsxs)("div",{className:"space-y-3",children:[L&&(0,b.jsxs)("div",{className:"border border-border rounded p-3 bg-accent",children:[(0,b.jsx)("div",{className:"text-sm font-medium text-foreground mb-2",children:"New Token"}),(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsx)(w.Input,{type:"password",value:N,onChange:a=>{var b;let c;return O(b=a.target.value),Q(""),void(S(c=E(b)),b&&!c&&Q("Invalid token format. Must start with sk-ant-api or sk-ant-oat"))},placeholder:"sk-ant-api... or sk-ant-oat...",className:"w-full font-mono",autoFocus:!0}),R&&!P&&(0,b.jsxs)("div",{className:"text-xs text-success",children:["→ Detected: ",D[R]]}),P&&(0,b.jsx)("div",{className:"text-xs text-destructive",children:P}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{M(!1),O(""),Q(""),S(null)},className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:W,disabled:!R||!!P,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]})]}),0!==g.length||L?g.map(c=>(0,b.jsx)("div",{className:"border border-border rounded p-3 space-y-2",children:n===c.key?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{className:"text-sm font-medium text-foreground mb-2",children:"Edit Token"}),(0,b.jsx)(w.Input,{type:"password",value:x,onChange:a=>{var b;let c;return z(b=a.target.value),G(""),void(I(c=E(b)),b&&!c&&G("Invalid token format. Must start with sk-ant-api or sk-ant-oat"))},placeholder:"sk-ant-api... or sk-ant-oat...",className:"w-full font-mono",autoFocus:!0}),H&&!A&&(0,b.jsxs)("div",{className:"text-xs text-success",children:["→ Detected: ",D[H]]}),A&&(0,b.jsx)("div",{className:"text-xs text-destructive",children:A}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:U,className:"active:scale-95",children:(0,b.jsx)(q.X,{className:"w-4 h-4"})}),(0,b.jsx)(m.Button,{size:"sm",onClick:()=>V(c.key),disabled:!H||!!A,className:"active:scale-95",children:(0,b.jsx)(r.Check,{className:"w-4 h-4"})})]})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-sm font-medium text-foreground",children:c.label}),(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>K(a=>({...a,[c.key]:!a[c.key]})),title:J[c.key]?"Hide value":"Show value",children:J[c.key]?(0,b.jsx)(t,{className:"w-4 h-4 text-muted-foreground"}):(0,b.jsx)(s.Eye,{className:"w-4 h-4 text-muted-foreground"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>{o(c.key),z(""),G(""),I(null)},title:"Edit",children:(0,b.jsx)(v.Pencil,{className:"w-4 h-4 text-muted-foreground"})}),"global"!==a.scope&&(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-lg",onClick:()=>X(c.key),className:"hover:bg-destructive/10",title:"Delete",children:(0,b.jsx)(u.Trash2,{className:"w-4 h-4 text-destructive"})})]})]}),(0,b.jsx)(w.Input,{type:J[c.key]?"text":"password",value:c.value,readOnly:!0,className:"w-full font-mono"})]})},c.key)):(0,b.jsx)("div",{className:"text-center text-muted-foreground text-sm py-4",children:"No Claude tokens configured"})]})]})}let G=(0,g.default)("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]);var H=a.i(49594),I=a.i(90002);function J(){let[a,d]=(0,c.useState)([]),[e,g]=(0,c.useState)({}),[h,i]=(0,c.useState)(null),[j,k]=(0,c.useState)(!1),[n,o]=(0,c.useState)(!1),p=(0,c.useCallback)(async()=>{try{let[a,b]=await Promise.all([fetch((0,f.apiUrl)("/api/repos")).then(a=>a.json()),fetch((0,f.apiUrl)("/api/tasks")).then(a=>a.json())]);d(a.data??[]);let c={};for(let a of b.data?.tasks??[]){let b=`${a.owner}/${a.repo}`;c[b]=(c[b]??0)+1}g(c)}catch(a){console.error("Failed to load repositories:",a)}},[]);(0,c.useEffect)(()=>{p()},[p]);let q=async()=>{if(h){k(!0);try{if(!(await fetch((0,f.apiUrl)(`/api/repos/${h.owner}/${h.repo}`),{method:"DELETE"})).ok)throw Error("Failed to delete repository");await p()}catch(a){console.error("Failed to delete repository:",a)}finally{k(!1),i(null)}}},r=(0,c.useCallback)(async(b,c)=>{let e=b+c;if(e<0||e>=a.length)return;let g=[...a];[g[b],g[e]]=[g[e],g[b]],d(g.map((a,b)=>({...a,order:b}))),o(!0);try{if(!(await fetch((0,f.apiUrl)("/api/repos/reorder"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({repoIds:g.map(a=>a.id)})})).ok)throw Error("Failed to reorder repositories")}catch(a){console.error("Failed to reorder repositories:",a),await p()}finally{o(!1)}},[a,p]);return 0===a.length?(0,b.jsx)("div",{className:"text-sm text-muted-foreground",children:"No repositories cloned yet."}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(I.ConfirmDialog,{open:null!==h,onOpenChange:a=>{a.open||i(null)},title:"Delete Repository",message:h?`Delete ${h.owner}/${h.repo}? This will also delete ${e[`${h.owner}/${h.repo}`]??0} associated task(s), all worktrees, and the bare repository. This action cannot be undone.`:"",confirmLabel:j?"Deleting...":"Delete",cancelLabel:"Cancel",onConfirm:q,variant:"danger"}),(0,b.jsx)("p",{className:"text-xs text-muted-foreground",children:"この並び順がトップページの列の並び順になります"}),(0,b.jsx)("div",{className:"space-y-2",children:a.map((c,d)=>{let f=`${c.owner}/${c.repo}`,g=(0,H.getRepoColor)(c.owner,c.repo),h=e[f]??0;return(0,b.jsxs)("div",{className:"flex items-center justify-between gap-2 rounded-md border border-border p-3",children:[(0,b.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,b.jsx)("span",{className:`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${g.bg} ${g.text}`,children:f}),(0,b.jsxs)("span",{className:"text-xs text-muted-foreground whitespace-nowrap",children:[h," task",1!==h?"s":""]})]}),(0,b.jsxs)("div",{className:"flex flex-shrink-0 items-center",children:[(0,b.jsx)(m.Button,{variant:"ghost",size:"icon",onClick:()=>r(d,-1),disabled:0===d||n,className:"text-muted-foreground",title:"Move up",children:(0,b.jsx)(G,{className:"size-4"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon",onClick:()=>r(d,1),disabled:d===a.length-1||n,className:"text-muted-foreground",title:"Move down",children:(0,b.jsx)(l,{className:"size-4"})}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon",onClick:()=>i(c),className:"text-muted-foreground hover:text-destructive",title:"Delete repository",children:(0,b.jsx)(u.Trash2,{className:"size-4"})})]})]},c.id)})})]})}var K=a.i(26807);function L({owner:a,repo:d,onDeleted:e}){let[g,h]=(0,c.useState)(!1),[i,j]=(0,c.useState)(""),[k,l]=(0,c.useState)(!1),n=`${a}/${d}`,o=i===n,p=async()=>{if(o){l(!0);try{if(!(await fetch((0,f.apiUrl)(`/api/repos/${a}/${d}`),{method:"DELETE"})).ok)throw Error("Failed to delete repository");e()}catch(a){console.error("Failed to delete repository:",a)}finally{l(!1),h(!1),j("")}}};return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"rounded-md border border-destructive/30 p-4 space-y-3",children:[(0,b.jsxs)("div",{className:"space-y-1",children:[(0,b.jsx)("h3",{className:"text-sm font-semibold text-destructive",children:"Remove Repository"}),(0,b.jsx)("p",{className:"text-xs text-muted-foreground",children:"Remove this repository and all associated data including tasks, worktrees, and environment variables. This action cannot be undone."})]}),(0,b.jsxs)(m.Button,{variant:"destructive",size:"sm",onClick:()=>h(!0),children:[(0,b.jsx)(u.Trash2,{className:"size-4"}),"Remove Repository"]})]}),(0,b.jsx)(K.Dialog,{open:g,onOpenChange:h,children:(0,b.jsxs)(K.DialogContent,{showCloseButton:!1,children:[(0,b.jsxs)(K.DialogHeader,{children:[(0,b.jsx)(K.DialogTitle,{children:"Remove Repository"}),(0,b.jsxs)(K.DialogDescription,{children:["This will permanently delete ",(0,b.jsx)("strong",{children:n})," and all associated tasks, worktrees, and environment variables."]})]}),(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsxs)("label",{className:"text-xs text-muted-foreground",children:["Type ",(0,b.jsx)("strong",{children:n})," to confirm"]}),(0,b.jsx)(w.Input,{value:i,onChange:a=>j(a.target.value),placeholder:n,autoComplete:"off"})]}),(0,b.jsxs)(K.DialogFooter,{children:[(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>{h(!1),j("")},disabled:k,children:"Cancel"}),(0,b.jsx)(m.Button,{variant:"destructive",size:"sm",onClick:p,disabled:!o||k,children:k?"Removing...":"Remove"})]})]})})]})}var M=a.i(67453),N=a.i(36620),O=a.i(96221),P=a.i(4975),Q=a.i(48124),R=a.i(92552),S=a.i(65025),T=a.i(97463),U=a.i(6828),V=a.i(56026);let W="tsunagi:voice-input-enabled",X={not_running:"停止中",installing_deps:"依存関係をインストール中...",downloading_model:"モデルをダウンロード中...",starting_server:"サーバーを起動中...",running:"実行中",running_external:"実行中 (tsunagi外で起動)",error:"エラー"},Y=["installing_deps","downloading_model","starting_server"],Z=["running","running_external"];function $(a){let b=a/0x40000000;return b>=.1?`${b.toFixed(2)} GB`:`${(a/1048576).toFixed(0)} MB`}function _(){let[a,d]=(0,c.useState)(!1),[e,g]=(0,c.useState)(!1),[h,i]=(0,c.useState)(null),[j,k]=(0,c.useState)(""),l=(0,c.useRef)(null),n=(0,c.useCallback)(a=>{d(a),localStorage.setItem(W,String(a))},[]),o=(0,c.useCallback)(a=>{k(a),localStorage.setItem(V.WHISPER_PROMPT_STORAGE_KEY,a)},[]),p=(0,c.useCallback)(async()=>{let a=await fetch((0,f.apiUrl)("/api/whisper/server/status")),b=await a.json();return i(b),b},[]);(0,c.useEffect)(()=>{d("true"===localStorage.getItem(W)),k(localStorage.getItem(V.WHISPER_PROMPT_STORAGE_KEY)??""),p()},[p]),(0,c.useEffect)(()=>{h&&Z.includes(h.step)&&!a&&(n(!0),U.toaster.create({type:"success",title:"音声入力が有効化されました"}))},[h,a,n]),(0,c.useEffect)(()=>(h&&Y.includes(h.step)&&!l.current&&(l.current=setInterval(()=>{p().then(a=>{!Y.includes(a.step)&&l.current&&(clearInterval(l.current),l.current=null)})},1e3)),()=>{l.current&&(clearInterval(l.current),l.current=null)}),[h,p]);let q=(0,c.useCallback)(()=>{p(),g(!0)},[p]),r=(0,c.useCallback)(async()=>{try{let a=await fetch((0,f.apiUrl)("/api/whisper/server/start"),{method:"POST"});if(!a.ok){let b=await a.json().catch(()=>null);throw Error(b?.error||`HTTPエラー: ${a.status}`)}i(await a.json())}catch(a){U.toaster.create({type:"error",title:"サーバーの起動に失敗しました",description:a instanceof Error?a.message:String(a)})}},[]),s=(0,c.useCallback)(async()=>{try{let a=await fetch((0,f.apiUrl)("/api/whisper/server/stop"),{method:"POST"});if(!a.ok){let b=await a.json().catch(()=>null);throw Error(b?.error||`HTTPエラー: ${a.status}`)}i(await a.json())}catch(a){U.toaster.create({type:"error",title:"サーバーの停止に失敗しました",description:a instanceof Error?a.message:String(a)})}},[]),t=(0,c.useCallback)(()=>{n(!1),h&&Z.includes(h.step)&&s()},[n,s,h]),u=h?.serverDir,v=h?.downloadProgress,w=v?v.downloadedBytes/v.totalBytes*100:0,x=null!==h,y=x&&Z.includes(h.step);return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsxs)("div",{className:"flex items-center gap-1",children:[(0,b.jsx)(R.CardTitle,{children:"音声入力 (実験的機能)"}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-sm",onClick:q,title:"音声入力について",children:(0,b.jsx)(N.CircleHelp,{})})]}),(0,b.jsx)(R.CardDescription,{children:"ローカルで動作するWhisperを使って音声入力を行います。下記のローカルLLMも有効にすると、 文字起こし結果がLLMで自動整形されます(無効時は文字起こし結果をそのまま使用)。"})]}),(0,b.jsx)(R.CardContent,{className:"flex flex-col gap-3",children:a?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[x?y?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"音声入力: 有効"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-warning",children:[(0,b.jsx)(B.AlertCircle,{className:"size-4"}),"音声入力: 有効化済み(サーバー停止中)"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"状態を確認中..."]}),h&&(0,b.jsxs)("span",{className:"text-xs/relaxed text-muted-foreground",children:["(",X[h.step],")"]}),x&&!y&&(0,b.jsxs)(m.Button,{size:"default",onClick:q,children:[(0,b.jsx)(P.Mic,{}),"サーバーを起動"]}),(0,b.jsx)(m.Button,{size:"default",variant:"outline",onClick:t,children:"無効にする"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:"文字起こしプロンプト (任意)"}),(0,b.jsx)(T.Textarea,{value:j,onChange:a=>o(a.target.value),placeholder:"例: 誤字、句読点、音声入力、Whisper、固有名詞や専門用語など",className:"min-h-16 text-xs"}),(0,b.jsx)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:"よく使う単語(固有名詞・専門用語・同音異義語で誤変換されやすい単語など)を列挙すると、 Whisperがその表記を優先しやすくなり誤変換が減ります。文章でなく単語の羅列でも構いません。空でも可。"})]})]}):(0,b.jsxs)(m.Button,{size:"default",onClick:q,children:[(0,b.jsx)(P.Mic,{}),"音声入力を有効化する"]})}),(0,b.jsx)(I.Dialog,{open:e,onOpenChange:({open:a})=>g(a),title:"音声入力について",maxWidth:"2xl",children:(0,b.jsxs)("div",{className:"space-y-4 text-sm",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"実験的機能です"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"音声入力はローカルで動作するWhisper (mlx-whisper) を利用します。精度・速度は環境に依存し、今後変更される可能性があります。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"対応環境"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"Apple Silicon Mac (M1/M2/M3/M4) のみ対応。Windows/Linuxでは利用できません。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"必要なもの(事前に手動でインストール)"}),(0,b.jsx)("ul",{className:"list-disc pl-5 text-muted-foreground",children:(0,b.jsx)("li",{children:"Python 3.9以降(Xcode Command Line Tools または Homebrew経由で入手可能)"})})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"mb-1 font-medium text-foreground",children:"セットアップ・起動"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"下のボタンから、依存関係のインストール・モデルのダウンロード・サーバー起動まで自動で行われます(初回は数分かかります)。"}),h&&!u&&(0,b.jsx)("p",{className:"mt-1 text-destructive",children:"whisper-serverが見つかりませんでした。インストールが壊れている可能性があります。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"mb-1 font-medium text-foreground",children:"アンインストール"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:["音声入力のためにダウンロードされるもの(Pythonの依存関係・Whisperモデル、合計約2.6GB)は全て",(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:"~/.tsunagi/whisper"}),"に保存されます。不要になった場合はこのディレクトリを削除するだけで、関連リソースを完全に削除できます。"]})]}),(0,b.jsxs)("div",{className:"border-t border-border pt-4",children:[(!h||"not_running"===h.step||"error"===h.step)&&(0,b.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void r(),disabled:!h,children:[h?(0,b.jsx)(P.Mic,{}):(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"Whisperサーバーを起動"]}),h?.step==="error"&&h.error&&(0,b.jsx)("p",{className:"text-xs/relaxed text-destructive",children:h.error})]}),h?.step==="installing_deps"&&(0,b.jsxs)(m.Button,{size:"default",disabled:!0,children:[(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"依存関係をインストール中... (数分かかる場合があります)"]}),h?.step==="downloading_model"&&(0,b.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 text-xs/relaxed text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"モデルをダウンロード中..."]}),v&&(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(S.Progress,{value:w}),(0,b.jsxs)("p",{className:"text-xs/relaxed text-muted-foreground",children:[$(v.downloadedBytes)," / ",$(v.totalBytes)," (",w.toFixed(0),"%) ・ ",function(a){if(null===a)return"残り時間を計算中...";if(a<60)return`残り約${a}秒`;let b=Math.floor(a/60);return`残り約${b}分${a%60}秒`}(v.etaSeconds)]})]})]}),h?.step==="starting_server"&&(0,b.jsxs)(m.Button,{size:"default",disabled:!0,children:[(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"サーバーを起動中..."]}),h&&Z.includes(h.step)&&(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"サーバーは起動しています"]}),(0,b.jsxs)(m.Button,{size:"default",variant:"outline",onClick:()=>void s(),children:[(0,b.jsx)(Q.Square,{}),"サーバーを停止"]})]})]})]})})]})}var aa=a.i(19768),ab=a.i(94392);let ac=(0,g.default)("memory-stick",[["path",{d:"M12 12v-2",key:"fwoke6"}],["path",{d:"M12 18v-2",key:"qj6yno"}],["path",{d:"M16 12v-2",key:"heuere"}],["path",{d:"M16 18v-2",key:"s1ct0w"}],["path",{d:"M2 11h1.5",key:"15p63e"}],["path",{d:"M20 18v-2",key:"12ehxp"}],["path",{d:"M20.5 11H22",key:"khsy7a"}],["path",{d:"M4 18v-2",key:"1c3oqr"}],["path",{d:"M8 12v-2",key:"1mwtfd"}],["path",{d:"M8 18v-2",key:"qcmpov"}],["rect",{x:"2",y:"6",width:"20",height:"10",rx:"2",key:"1qcswk"}]]);var ad=a.i(25015);let ae=(0,g.default)("power-off",[["path",{d:"M18.36 6.64A9 9 0 0 1 20.77 15",key:"dxknvb"}],["path",{d:"M6.16 6.16a9 9 0 1 0 12.68 12.68",key:"1x7qb5"}],["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);var af=a.i(69520),ag=a.i(95490),ah=a.i(1464),ai=a.i(12223);let aj={k:1024,m:1048576},ak=[32768,65536,131072,262144];function al(a){let b=a.trim().replace(/[,_\s]/g,"").toLowerCase().match(/^(\d+(?:\.\d+)?)([km]?)$/);if(!b)return null;let c=Number(b[1])*(b[2]?aj[b[2]]:1);return Number.isInteger(c)&&c>0?c:null}function am(a){return a>=aj.m&&a%aj.m==0?`${a/aj.m}m`:a>=aj.k&&a%aj.k==0?`${a/aj.k}k`:String(a)}function an({value:a,onChange:d,max:e}){let f=(0,c.useId)(),g=al(a),h=null!==g&&void 0!==e&&e>0&&g>e,i=ak.filter(a=>!e||a<=e);return(0,b.jsxs)("div",{children:[(0,b.jsx)(w.Input,{value:a,onChange:a=>d(a.target.value),placeholder:"64k",list:f,"aria-invalid":null===g||h,className:"font-mono"}),(0,b.jsx)("datalist",{id:f,children:i.map(a=>(0,b.jsx)("option",{value:am(a)},a))}),(0,b.jsx)("p",{className:`mt-1 text-[0.65rem] ${null===g||h?"text-destructive":"text-muted-foreground"}`,children:null===g?"64k / 128k / 1m または整数で入力してください(k = 1024)":h?`このモデルの最大値(${am(e)})を超えています`:`${g.toLocaleString()} tokens`})]})}var k=k;async function ao(a,b){let c=await fetch((0,f.apiUrl)(a),b),d=await c.json().catch(()=>null);if(!c.ok||d?.data===void 0)throw Error(d?.error||`HTTPエラー: ${c.status}`);return d.data}function ap(a,b){return ao(a,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(b)})}function aq(a){return a instanceof Error?a.message:String(a)}function ar({children:a}){return(0,b.jsx)("div",{className:"flex flex-wrap items-center gap-2 rounded-md border border-border bg-muted/30 px-3 py-2 text-sm",children:a})}function as({label:a,hint:c,children:d}){return(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"mb-1 block text-xs font-medium text-muted-foreground",children:a}),d,c&&(0,b.jsx)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:c})]})}function at({children:a}){let[d,e]=(0,c.useState)(!1);return(0,b.jsxs)("div",{children:[(0,b.jsxs)("button",{type:"button",onClick:()=>e(a=>!a),className:"flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",children:[(0,b.jsx)(k.default,{className:`size-3.5 transition-transform ${d?"rotate-90":""}`}),"詳細設定"]}),d&&(0,b.jsx)("div",{className:"mt-3 flex flex-col gap-3 border-l border-border pl-3",children:a})]})}function au({children:a}){return(0,b.jsx)("code",{className:"rounded bg-muted px-1",children:a})}let av={ollama:"Ollama",lmstudio:"LM Studio"};function aw(a,b){return`${a}:${b}`}function ax(a){let b=a.indexOf(":");if(b<0)return null;let c=a.slice(0,b);return"ollama"!==c&&"lmstudio"!==c?null:{provider:c,model:a.slice(b+1)}}function ay({status:a}){let c=a.active?`${a.active.model}(${av[a.active.provider]}・${am(a.active.contextTokens)})`:"";switch(a.state){case"unconfigured":return(0,b.jsx)("span",{className:"text-muted-foreground",children:"使用するモデルが未設定です"});case"loading":return(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"読み込み中: ",c]});case"loaded":return(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"読み込み済み: ",c]});case"unloaded":return(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(ac,{className:"size-4"}),"解放済み: ",c,"(次の発言で読み込みます)"]});case"error":return(0,b.jsxs)("span",{className:"flex items-center gap-2 text-destructive",children:[(0,b.jsx)(B.AlertCircle,{className:"size-4"}),a.error]})}}function az(){var a;let d,{settings:e,setSettings:f}=(0,ai.useLocalLlmSettings)(),[g,h]=(0,c.useState)(null),[i,j]=(0,c.useState)(null),[k,l]=(0,c.useState)(null),[n,o]=(0,c.useState)(!1),[p,q]=(0,c.useState)(null),[r,s]=(0,c.useState)(!1),[t,u]=(0,c.useState)(!1),[v,x]=(0,c.useState)(!1);(0,c.useEffect)(()=>{var a;e&&h({selection:(a=e).active?aw(a.active.provider,a.active.model):"",context:am(a.active?.contextTokens??65536),idleUnloadMinutes:String(a.idleUnloadMinutes),unloadOnExit:a.unloadOnExit,webSearch:a.webSearch,extraEnvText:Object.entries(a.extraEnv).map(([a,b])=>`${a}=${b}`).join("\n")})},[e]);let y=(0,c.useCallback)(async()=>{try{j(await ao("/api/settings/local-llm/status"))}catch(a){console.error("Failed to fetch local LLM status:",a)}},[]),z=(0,c.useCallback)(async()=>{o(!0);try{l(await ao("/api/settings/local-llm/models"))}catch(a){U.toaster.create({type:"error",title:"モデル一覧を取得できません",description:aq(a)})}finally{o(!1)}},[]);(0,c.useEffect)(()=>{y(),z();let a=setInterval(()=>void y(),3e3);return()=>clearInterval(a)},[y,z]);let A=g?ax(g.selection):null,B=(0,c.useMemo)(()=>k?.models.find(a=>a.provider===A?.provider&&a.model===A?.model),[k,A?.provider,A?.model]),C=B?.maxContextLength??void 0,D=A?.provider==="lmstudio"?A.model:"",E=g?al(g.context):null;(0,c.useEffect)(()=>{if(q(null),!D||!E)return;let a=new AbortController,b=setTimeout(()=>{let b=new URLSearchParams({model:D,contextTokens:String(E)});ao(`/api/settings/local-llm/estimate?${b}`,{signal:a.signal}).then(q).catch(()=>q(null))},600);return()=>{clearTimeout(b),a.abort()}},[D,E]);let F=Number(g?.idleUnloadMinutes),G=null!==g&&(a=g.context,null!==(d=al(a))&&(!C||d<=C))&&Number.isInteger(F)&&F>=0,H=(0,c.useCallback)(async()=>{if(!g||!G)return;let a=ax(g.selection),b={active:a?{...a,contextTokens:al(g.context)??65536}:null,idleUnloadMinutes:Number(g.idleUnloadMinutes),unloadOnExit:g.unloadOnExit,webSearch:g.webSearch,extraEnv:function(a){let b={};for(let c of a.split("\n")){let a=c.trim();if(!a||a.startsWith("#"))continue;let d=a.indexOf("=");d<=0||(b[a.slice(0,d).trim()]=a.slice(d+1).trim())}return b}(g.extraEnvText)},c=JSON.stringify(e?.active)!==JSON.stringify(b.active);s(!0);try{f(await ap("/api/settings/local-llm",b)),U.toaster.create({type:"success",title:c?"使用するモデルを切り替えました(他のモデルは解放します)":"ローカルLLMの設定を保存しました"}),y()}catch(a){U.toaster.create({type:"error",title:"ローカルLLMの設定を保存できませんでした",description:aq(a)})}finally{s(!1)}},[g,G,e?.active,f,y]),J=(0,c.useCallback)(async(a,b)=>{u(!0);try{j(await ao(a,{method:"POST"}))}catch(a){U.toaster.create({type:"error",title:b,description:aq(a)})}finally{u(!1)}},[]),K=a=>h(b=>b?{...b,...a}:b),L=(k?.models??[]).map(a=>{var b;return{value:aw(a.provider,a.model),label:[a.displayName,a.format.toUpperCase(),a.sizeBytes?(b=a.sizeBytes)>=0x40000000?`${(b/0x40000000).toFixed(1)} GB`:`${Math.round(b/1048576)} MB`:null,a.maxContextLength?`最大 ${am(a.maxContextLength)}`:null].filter(Boolean).join(" · "),group:av[a.provider]}}),M=e?.active;M&&!L.some(a=>a.value===aw(M.provider,M.model))&&L.unshift({value:aw(M.provider,M.model),label:`${M.model}(一覧にありません)`,group:av[M.provider]});let P=null!==k&&0===k.models.length&&0===k.errors.length;return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsxs)("div",{className:"flex items-center gap-1",children:[(0,b.jsx)(R.CardTitle,{children:"Claude Code のローカルLLM (実験的機能)"}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-sm",onClick:()=>x(!0),title:"ローカルLLMについて",children:(0,b.jsx)(N.CircleHelp,{})})]}),(0,b.jsxs)(R.CardDescription,{children:["Ollama / LM Studio のローカルLLMで Claude Code を起動します。",(0,b.jsx)("strong",{className:"font-medium text-foreground",children:"使用するモデルは1つだけで、全てのローカルLLMタブで共有します"}),"。切り替えると他のモデルはメモリから解放されます。"]})]}),(0,b.jsx)(R.CardContent,{className:"flex flex-col gap-3",children:e&&g?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(ar,{children:[i?(0,b.jsx)(ay,{status:i}):(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),(0,b.jsxs)("div",{className:"ml-auto flex items-center gap-2",children:[i?.state==="unloaded"&&(0,b.jsxs)(m.Button,{variant:"outline",size:"sm",onClick:()=>void J("/api/settings/local-llm/load","モデルを読み込めません"),disabled:t,children:[(0,b.jsx)(ad.Play,{}),"読み込む"]}),(i?.state==="loaded"||i?.state==="error")&&(0,b.jsxs)(m.Button,{variant:"outline",size:"sm",onClick:()=>void J("/api/settings/local-llm/unload","モデルを解放できません"),disabled:t||(i?.inflight??0)>0,title:"メモリから外す(次の発言で自動で読み込み直します)",children:[t?(0,b.jsx)(O.Loader2,{className:"animate-spin"}):(0,b.jsx)(ae,{}),"解放"]})]})]}),i&&i.inflight>0&&(0,b.jsxs)("p",{className:"text-[0.65rem] text-muted-foreground",children:["応答を生成中のタブがあります(",i.inflight,"件)。完了するまでモデルは切り替えられません。"]}),P?(0,b.jsx)("p",{className:"text-xs text-warning",children:"下の Ollama / LM Studio のどちらかを有効にすると、モデルを選べるようになります。"}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(as,{label:"使用するモデル",hint:k?.errors.length?(0,b.jsx)("span",{className:"text-destructive",children:k.errors.map(a=>`${av[a.provider]}: ${a.message}`).join(" / ")}):`有効なプロバイダーにダウンロード済みのモデル(${k?.models.length??0}件)`,children:(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)(ag.Combobox,{options:L,value:g.selection,onChange:a=>K({selection:String(a)}),placeholder:"モデルを選択",className:"flex-1"}),(0,b.jsx)(m.Button,{variant:"outline",size:"icon",onClick:()=>void z(),disabled:n,title:"モデル一覧を再取得",children:(0,b.jsx)(af.RefreshCw,{className:n?"animate-spin":void 0})})]})}),(0,b.jsxs)(as,{label:"コンテキスト長",children:[(0,b.jsx)(an,{value:g.context,onChange:a=>K({context:a}),max:C}),A?.provider==="lmstudio"&&(0,b.jsxs)("p",{className:"mt-1 flex items-center gap-1 text-[0.65rem] text-muted-foreground",children:[(0,b.jsx)(ab.Cpu,{className:"size-3"}),"必要メモリ(見積もり): ",p?.totalMemory??"-",B?.format==="mlx"&&"。MLX はモデルの最大値で読み込まれ、メモリは使った分だけ増えます"]}),A?.provider==="ollama"&&(0,b.jsxs)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:["このコンテキスト長を固定した派生モデル(",(0,b.jsx)(au,{children:"<モデル>-tsunagi-ctx<長さ>"}),")を作成して使います(重みは共有されます)。"]})]})]}),(0,b.jsx)(as,{label:"自動解放(分)",hint:"最後のリクエストからこの時間がたったらモデルをメモリから外します(0 で無効)。次の発言で自動で読み込み直します",children:(0,b.jsx)(w.Input,{type:"number",min:0,value:g.idleUnloadMinutes,onChange:a=>K({idleUnloadMinutes:a.target.value}),className:"w-32 font-mono"})}),(0,b.jsxs)("label",{className:"flex items-center gap-2 text-sm",children:[(0,b.jsx)("input",{type:"checkbox",checked:g.unloadOnExit,onChange:a=>K({unloadOnExit:a.target.checked}),className:"size-4 accent-primary"}),"tsunagi の終了時にモデルを解放する"]}),(0,b.jsxs)(as,{label:"WebSearch",children:[(0,b.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,b.jsx)(m.Button,{size:"sm",variant:"local"===g.webSearch?"default":"outline",onClick:()=>K({webSearch:"local"}),children:"ローカル検索(SearXNG)"}),(0,b.jsx)(m.Button,{size:"sm",variant:"ollama"===g.webSearch?"default":"outline",onClick:()=>K({webSearch:"ollama"}),children:"ollama.com(Ollama のみ・要サインイン)"})]}),(0,b.jsxs)("p",{className:"mt-1 text-[0.65rem] text-muted-foreground",children:["local"===g.webSearch?"組み込みの WebSearch を無効化し、ローカル検索(SearXNG)の web_search ツールを使います。":"使用するモデルが Ollama のとき、Ollama が ollama.com の Web 検索 API で代行します(Ollama 欄でサインイン状態を確認できます)。LM Studio のときはローカル検索になります。","設定はこの後に作成・起動したタブから反映されます。"]})]}),(0,b.jsx)(at,{children:(0,b.jsx)(as,{label:"追加の環境変数 (任意)",hint:"ローカルLLMタブにのみ適用されます。同名の既定値より優先されます",children:(0,b.jsx)(T.Textarea,{value:g.extraEnvText,onChange:a=>K({extraEnvText:a.target.value}),placeholder:"KEY=VALUE(1行に1つ)",className:"min-h-16 font-mono text-xs"})})}),(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void H(),disabled:r||!G,children:[r?(0,b.jsx)(O.Loader2,{className:"animate-spin"}):A&&(0,b.jsx)(ah.LocalLlmIcon,{provider:A.provider,className:"size-4"}),"保存"]}),(0,b.jsx)("span",{className:"text-[0.65rem] text-muted-foreground",children:"モデルを変えて保存すると、他のモデルを解放して読み込みを始めます"})]})]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"読み込み中..."]})}),(0,b.jsx)(I.Dialog,{open:v,onOpenChange:({open:a})=>x(a),title:"ローカルLLMについて",maxWidth:"2xl",children:(0,b.jsxs)("div",{className:"space-y-4 text-sm",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"実験的機能です"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"Claude Code の接続先を tsunagi の中継口に切り替え、tsunagi が Ollama / LM Studio の Anthropic 互換 API に転送します。Anthropic はClaude以外のモデルへの接続をサポートしていないため、動作は保証されません。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"モデルは1つだけ"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"20〜30GB 級のモデルを2つ同時にメモリへ載せられるマシンは少ないため、使用するモデルは1つにし、全てのローカルLLMタブで共有します。切り替えると他のモデルは解放され、各タブは次の発言で会話全体を新しいモデルで読み直します(数十秒〜数分)。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"/model について"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:["ローカルLLMタブでは ",(0,b.jsx)(au,{children:"/model"})," ","によるモデルの切り替えを無効にしています(Claude Code が切り替えたモデルを通常の Claude タブの既定値として保存してしまうため)。切り替えはここで行ってください。"]})]})]})})]})}var aA=a.i(52495),aB=a.i(83604),aB=aB;function aC(){let{settings:a,setSettings:d}=(0,ai.useOllamaSettings)(),[e,f]=(0,c.useState)(""),[g,i]=(0,c.useState)(!1),[j,k]=(0,c.useState)(null),[l,n]=(0,c.useState)(null),[o,p]=(0,c.useState)(!1),[q,r]=(0,c.useState)(null);(0,c.useEffect)(()=>{a&&f(a.baseUrl)},[a]);let s=(0,c.useCallback)(async a=>{i(!0);try{return d(await ap("/api/settings/ollama",a)),!0}catch(a){return U.toaster.create({type:"error",title:"Ollama の設定を保存できませんでした",description:aq(a)}),!1}finally{i(!1)}},[d]),t=(0,c.useCallback)(async a=>{try{k(await ao(`/api/settings/ollama/status?baseUrl=${encodeURIComponent(a)}`))}catch(a){console.error("Failed to fetch Ollama status:",a)}},[]),u=(0,c.useCallback)(async a=>{p(!0),r(null);try{n(await ao(`/api/settings/ollama/account?baseUrl=${encodeURIComponent(a)}`))}catch(a){n(null),r(aq(a))}finally{p(!1)}},[]),v=a?.enabled===!0,x=a?.baseUrl;(0,c.useEffect)(()=>{if(!v||!x)return;t(x),u(x);let a=setInterval(()=>void t(x),5e3);return()=>clearInterval(a)},[v,x,t,u]);let y=(0,c.useCallback)(async()=>{a&&await s({...a,baseUrl:e})&&U.toaster.create({type:"success",title:"Ollama の設定を保存しました"})},[a,e,s]);return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsx)(R.CardTitle,{children:"Ollama"}),(0,b.jsxs)(R.CardDescription,{children:["ローカルLLMのプロバイダーとして Ollama を使います。Ollama のインストール・モデルの pull・起動はご自身で行ってください(例:"," ",(0,b.jsx)(au,{children:"ollama pull qwen3.6:35b-a3b-coding-nvfp4"}),")。"]})]}),(0,b.jsx)(R.CardContent,{className:"flex flex-col gap-3",children:a?v?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(ar,{children:[j?j.reachable?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"接続中",j.version&&` (v${j.version})`]}),(0,b.jsx)("span",{className:"text-xs text-muted-foreground",children:j.loaded.length>0?`読み込み中: ${j.loaded.map(a=>`${a.name}${a.contextLength?` (${am(a.contextLength)})`:""}`).join(", ")}`:"読み込み中のモデルなし"})]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-warning",children:[(0,b.jsx)(aB.default,{className:"size-4"}),"Ollama に接続できません。Ollama アプリを起動してください"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"確認中..."]}),(0,b.jsx)(m.Button,{variant:"outline",size:"sm",className:"ml-auto",onClick:()=>void s({...a,enabled:!1}),disabled:g,children:"無効にする"})]}),(0,b.jsx)(as,{label:"ollama.com(WebSearch を Ollama に代行させる場合)",hint:(0,b.jsxs)(b.Fragment,{children:["「Claude Code のローカルLLM」欄の WebSearch を「ollama.com」にした場合のみ必要です。Ollama を動かしているマシンで"," ",(0,b.jsx)(au,{children:"ollama signin"})," を実行してください(検索クエリは ollama.com に送信されます)。"]}),children:(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[o?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"確認中..."]}):l?.signedIn?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(h,{className:"size-4"}),"サインイン済み(",l.name,")"]}):l?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(aB.default,{className:"size-4"}),"未サインイン"]}),l.signinUrl&&(0,b.jsxs)("a",{href:l.signinUrl,target:"_blank",rel:"noreferrer",className:(0,m.buttonVariants)({variant:"outline",size:"sm"}),children:[(0,b.jsx)(aA.ExternalLink,{}),"サインイン"]})]}):(0,b.jsx)("span",{className:"text-xs text-destructive",children:q}),(0,b.jsx)(m.Button,{variant:"outline",size:"icon",onClick:()=>void u(a.baseUrl),disabled:o,title:"サインイン状態を再確認",children:(0,b.jsx)(af.RefreshCw,{className:o?"animate-spin":void 0})})]})}),(0,b.jsx)(at,{children:(0,b.jsx)(as,{label:"Base URL",hint:(0,b.jsxs)(b.Fragment,{children:["Docker で tsunagi を動かしている場合は"," ",(0,b.jsx)(au,{children:"http://host.docker.internal:11434"})]}),children:(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)(w.Input,{value:e,onChange:a=>f(a.target.value),placeholder:"http://localhost:11434"}),(0,b.jsx)(m.Button,{size:"default",onClick:()=>void y(),disabled:g||e===a.baseUrl,children:"保存"})]})})})]}):(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void s({...a,enabled:!0}),disabled:g,children:[(0,b.jsx)(ah.OllamaIcon,{className:"size-4"}),"Ollama を有効化する"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"読み込み中..."]})})]})}var aB=aB;function aD(){let{settings:a,setSettings:d}=(0,ai.useLmStudioSettings)(),[e,f]=(0,c.useState)(null),[g,h]=(0,c.useState)(!1),[i,j]=(0,c.useState)(null),[k,l]=(0,c.useState)(!1);(0,c.useEffect)(()=>{a&&f({baseUrl:a.baseUrl,apiToken:a.apiToken,lmsPath:a.lmsPath})},[a]);let n=a?.enabled===!0,o=(0,c.useCallback)(async()=>{try{j(await ao("/api/settings/lmstudio/status"))}catch(a){console.error("Failed to fetch LM Studio status:",a)}},[]);(0,c.useEffect)(()=>{if(!n)return;o();let a=setInterval(()=>void o(),5e3);return()=>clearInterval(a)},[n,o]);let p=(0,c.useCallback)(async a=>{h(!0);try{return d(await ap("/api/settings/lmstudio",a)),!0}catch(a){return U.toaster.create({type:"error",title:"LM Studio の設定を保存できませんでした",description:aq(a)}),!1}finally{h(!1)}},[d]),q=(0,c.useCallback)(async a=>{l(!0);try{j(await ao(`/api/settings/lmstudio/server/${a}`,{method:"POST"}))}catch(b){U.toaster.create({type:"error",title:"start"===a?"サーバーを起動できません":"サーバーを停止できません",description:aq(b)})}finally{l(!1)}},[]),r=(0,c.useCallback)(async()=>{a&&e&&await p({...a,...e})&&(U.toaster.create({type:"success",title:"LM Studio の設定を保存しました"}),o())},[a,e,p,o]),s=a=>f(b=>b?{...b,...a}:b);return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsx)(R.CardTitle,{children:"LM Studio"}),(0,b.jsxs)(R.CardDescription,{children:["ローカルLLMのプロバイダーとして LM Studio(0.4.1 以降)を使います。",(0,b.jsx)("a",{href:"https://lmstudio.ai/download",target:"_blank",rel:"noreferrer",className:"underline",children:"LM Studio"}),"のインストールとモデルのダウンロードはご自身で行ってください(例:"," ",(0,b.jsx)(au,{children:"mlx-community/Qwen3.6-35B-A3B-4bit"}),")。一度起動すると lms CLI が入ります。"]})]}),(0,b.jsx)(R.CardContent,{className:"flex flex-col gap-3",children:a&&e?n?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(ar,{children:[i?i.serverRunning?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"サーバー起動中"]}),(0,b.jsx)("span",{className:"text-xs text-muted-foreground",children:i.loaded.length>0?`読み込み中: ${i.loaded.map(a=>`${a.key} (${am(a.contextLength)})`).join(", ")}`:"読み込み中のモデルなし"})]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-warning",children:[(0,b.jsx)(aB.default,{className:"size-4"}),"サーバー停止中"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"確認中..."]}),(0,b.jsxs)("div",{className:"ml-auto flex items-center gap-2",children:[i&&i.lmsPath?i.serverRunning?(0,b.jsxs)(m.Button,{variant:"outline",size:"sm",onClick:()=>void q("stop"),disabled:k,children:[k?(0,b.jsx)(O.Loader2,{className:"animate-spin"}):(0,b.jsx)(Q.Square,{}),"停止"]}):(0,b.jsxs)(m.Button,{size:"sm",onClick:()=>void q("start"),disabled:k,children:[k?(0,b.jsx)(O.Loader2,{className:"animate-spin"}):(0,b.jsx)(ad.Play,{}),"起動"]}):null,(0,b.jsx)(m.Button,{variant:"outline",size:"sm",onClick:()=>void p({...a,enabled:!1}),disabled:g,children:"無効にする"})]})]}),i&&!i.lmsPath&&!i.serverRunning&&(0,b.jsxs)("p",{className:"text-xs text-muted-foreground",children:["tsunagi から LM Studio のサーバーを起動するための lms CLI が見つかりません(tsunagi を Docker で動かしている場合も同様です)。LM Studio アプリの Developer タブでサーバーを起動するか、LM Studio を動かしているマシンで"," ",(0,b.jsx)(au,{children:"lms server start"})," を実行してください。lms がある場合は詳細設定でパスを指定できます。"]}),(0,b.jsxs)(at,{children:[(0,b.jsx)(as,{label:"Base URL",children:(0,b.jsx)(w.Input,{value:e.baseUrl,onChange:a=>s({baseUrl:a.target.value}),placeholder:"http://localhost:1234"})}),(0,b.jsx)(as,{label:"API トークン (任意)",hint:"LM Studio で「Require Authentication」を有効にしている場合のみ",children:(0,b.jsx)(w.Input,{type:"password",value:e.apiToken,onChange:a=>s({apiToken:a.target.value})})}),(0,b.jsx)(as,{label:"lms のパス (任意)",hint:"空欄なら ~/.lmstudio/bin/lms → PATH の順で探します",children:(0,b.jsx)(w.Input,{value:e.lmsPath,onChange:a=>s({lmsPath:a.target.value}),placeholder:i?.lmsPath??"~/.lmstudio/bin/lms",className:"font-mono"})}),(0,b.jsx)("div",{children:(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void r(),disabled:g,children:[g&&(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"保存"]})})]})]}):(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void p({...a,enabled:!0}),disabled:g,children:[(0,b.jsx)(ah.LmStudioIcon,{className:"size-4"}),"LM Studio を有効化する"]}):(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"読み込み中..."]})})]})}let aE=(0,g.default)("package-x",[["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14",key:"e7tb2h"}],["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}],["polyline",{points:"3.29 7 12 12 20.71 7",key:"ousv84"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12",key:"a4e8g8"}],["path",{d:"m17 13 5 5m-5 0 5-5",key:"im3w4b"}]]),aF=(0,g.default)("rotate-cw",[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]]);function aG(){let[a,d]=(0,c.useState)(null),[e,f]=(0,c.useState)(null),[g,h]=(0,c.useState)(null),[i,j]=(0,c.useState)(!1),[k,l]=(0,c.useState)(!1),n=(0,c.useCallback)(async()=>{try{d(await ao("/api/settings/searxng/status"))}catch(a){console.error("Failed to fetch SearXNG status:",a)}},[]);(0,c.useEffect)(()=>{n(),ao("/api/settings/searxng").then(f).catch(a=>console.error("Failed to fetch SearXNG settings:",a));let a=setInterval(()=>void n(),3e3);return()=>clearInterval(a)},[n]),(0,c.useEffect)(()=>{e&&h({port:String(e.port),binPath:e.binPath,settingsPath:e.settingsPath})},[e]);let o=(0,c.useCallback)(async(a,b)=>{j(!0);try{d(await ao(a,{method:"POST"}))}catch(a){U.toaster.create({type:"error",title:b,description:aq(a)})}finally{j(!1)}},[]),p=(0,c.useCallback)(async()=>{if(g){j(!0);try{f(await ap("/api/settings/searxng",{port:Number(g.port),binPath:g.binPath,settingsPath:g.settingsPath}))}catch(a){U.toaster.create({type:"error",title:"SearXNG の設定を保存できませんでした",description:aq(a)}),j(!1);return}j(!1),await o("/api/settings/searxng/restart","SearXNG を再起動できません")}},[g,o]);if(!a?.required)return null;let q=a=>h(b=>b?{...b,...a}:b);return(0,b.jsxs)(R.Card,{children:[(0,b.jsxs)(R.CardHeader,{children:[(0,b.jsxs)("div",{className:"flex items-center gap-1",children:[(0,b.jsx)(R.CardTitle,{children:"ローカル検索 (SearXNG)"}),(0,b.jsx)(m.Button,{variant:"ghost",size:"icon-sm",onClick:()=>l(!0),title:"ローカル検索について",children:(0,b.jsx)(N.CircleHelp,{})})]}),(0,b.jsxs)(R.CardDescription,{children:["Ollama / LM Studio タブの WebSearch をローカルの SearXNG で行います。",(0,b.jsx)("strong",{className:"font-medium text-foreground",children:"Ollama か LM Studio が有効な間、tsunagi が自動で起動・停止します"}),"。SearXNG のインストールはご自身で行ってください。"]})]}),(0,b.jsxs)(R.CardContent,{className:"flex flex-col gap-3",children:[(0,b.jsxs)(ar,{children:["running"===a.state||"external"===a.state?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("span",{className:"flex items-center gap-2 text-success",children:[(0,b.jsx)(M.CheckCircle2,{className:"size-4"}),"running"===a.state?"起動中":"起動中(tsunagi 外で起動)"]}),(0,b.jsx)("span",{className:"font-mono text-xs text-muted-foreground",children:a.url})]}):"starting"===a.state?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-muted-foreground",children:[(0,b.jsx)(O.Loader2,{className:"size-4 animate-spin"}),"起動中..."]}):"not-installed"===a.state?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-warning",children:[(0,b.jsx)(aE,{className:"size-4"}),"SearXNG が見つかりません(",(0,b.jsx)(au,{children:"searxng-run"}),")"]}):"error"===a.state?(0,b.jsxs)("span",{className:"flex items-center gap-2 text-destructive",children:[(0,b.jsx)(B.AlertCircle,{className:"size-4"}),"エラー"]}):(0,b.jsx)("span",{className:"text-muted-foreground",children:"停止中"}),(0,b.jsxs)("div",{className:"ml-auto flex items-center gap-2",children:["external"!==a.state&&"starting"!==a.state&&(0,b.jsxs)(m.Button,{variant:"outline",size:"sm",onClick:()=>void o("/api/settings/searxng/restart","SearXNG を起動できません"),disabled:i,children:[(0,b.jsx)(aF,{}),"running"===a.state?"再起動":"起動"]}),"running"===a.state&&(0,b.jsxs)(m.Button,{variant:"outline",size:"sm",onClick:()=>void o("/api/settings/searxng/stop","SearXNG を停止できません"),disabled:i,children:[(0,b.jsx)(Q.Square,{}),"停止"]})]})]}),"error"===a.state&&a.error&&(0,b.jsx)("pre",{className:"max-h-40 overflow-auto rounded-md bg-muted p-2 text-[0.65rem] whitespace-pre-wrap text-destructive",children:a.error}),"not-installed"===a.state&&(0,b.jsxs)("p",{className:"text-xs text-muted-foreground",children:["nix なら ",(0,b.jsx)(au,{children:"nix profile install nixpkgs#searxng"})," などで"," ",(0,b.jsx)(au,{children:"searxng-run"})," を PATH に入れてください(",(0,b.jsx)("a",{href:"https://docs.searxng.org/admin/installation.html",target:"_blank",rel:"noreferrer",className:"underline",children:"インストール方法"}),")。PATH にない場合は詳細設定でパスを指定できます。"]}),g&&(0,b.jsxs)(at,{children:[(0,b.jsx)(as,{label:"ポート",hint:"既定は 7964(キーパッドで sxng)",children:(0,b.jsx)(w.Input,{type:"number",min:1,max:65535,value:g.port,onChange:a=>q({port:a.target.value}),className:"font-mono"})}),(0,b.jsx)(as,{label:"searxng-run のパス (任意)",hint:"空欄なら PATH から探します",children:(0,b.jsx)(w.Input,{value:g.binPath,onChange:a=>q({binPath:a.target.value}),placeholder:a.binPath??"searxng-run",className:"font-mono"})}),(0,b.jsx)(as,{label:"settings.yml のパス (任意)",hint:"空欄なら tsunagi が生成したもの(~/.tsunagi/searxng/settings.yml)を使います。独自のものを使う場合は search.formats に json を含めてください",children:(0,b.jsx)(w.Input,{value:g.settingsPath,onChange:a=>q({settingsPath:a.target.value}),className:"font-mono"})}),(0,b.jsx)("div",{children:(0,b.jsxs)(m.Button,{size:"default",onClick:()=>void p(),disabled:i,children:[i&&(0,b.jsx)(O.Loader2,{className:"animate-spin"}),"保存して再起動"]})})]})]}),(0,b.jsx)(I.Dialog,{open:k,onOpenChange:({open:a})=>l(a),title:"ローカル検索について",maxWidth:"2xl",children:(0,b.jsxs)("div",{className:"space-y-4 text-sm",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"仕組み"}),(0,b.jsxs)("p",{className:"text-muted-foreground",children:["Claude Code の WebSearch は Anthropic のサーバーツールのため、ローカルLLMでは使えません(LM Studio は無視し、Ollama は ollama.com のサインインが必要)。ローカル検索を使うタブでは WebSearch を無効化し、tsunagi の MCP が提供する ",(0,b.jsx)(au,{children:"web_search"})," ツールで SearXNG に検索させます。"]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"自動起動・停止"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"Ollama か LM Studio が有効なら、tsunagi の起動時・有効化時に SearXNG を起動し、両方を無効にしたときと tsunagi の終了時に停止します。既にポートで SearXNG が動いていればそれを使います(tsunagi は止めません)。SearXNG がなくても tsunagi 自体は通常どおり動きます。"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("p",{className:"font-medium text-foreground",children:"注意"}),(0,b.jsx)("p",{className:"text-muted-foreground",children:"SearXNG は Google / Bing / DuckDuckGo などの検索エンジンに問い合わせます。短時間に大量に検索すると、検索エンジン側で一時的にブロックされることがあります。"})]})]})})]})}var aH=a.i(78512);a.s(["default",0,function(){let a=(0,d.useRouter)();(0,aH.useDocumentTitle)("settings");let g=()=>({scope:"global",label:"Global"}),[h,i]=(0,c.useState)(null),[j,k]=(0,c.useState)(0),[l,n]=(0,c.useState)({completed:!0,hasGlobalToken:!0});return(0,c.useEffect)(()=>{fetch((0,f.apiUrl)("/api/onboarding/status")).then(a=>a.json()).then(a=>{let b=a.data;n(b),b.completed||b.hasGlobalToken?i(g()):i({scope:"global",label:"Global"})}).catch(a=>{console.error("Failed to fetch onboarding status:",a),i(g())})},[]),(0,c.useEffect)(()=>{h&&localStorage.setItem("tsunagi:env-selected-node",JSON.stringify(h))},[h]),(0,b.jsxs)("div",{className:"h-screen flex flex-col bg-background",children:[(0,b.jsx)("div",{className:"sticky top-0 z-50 p-4 border-b border-border bg-card",children:(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsxs)(m.Button,{variant:"ghost",onClick:()=>a.push("/"),className:"text-primary font-medium hover:bg-primary/10 hover:text-foreground",children:[(0,b.jsx)(e.ArrowLeft,{className:"w-4 h-4"}),"Back to Board"]}),(0,b.jsx)("h1",{className:"text-xl font-bold text-foreground absolute left-1/2 -translate-x-1/2",children:"Settings"})]})}),(0,b.jsxs)("div",{className:"flex-1 flex min-h-0",children:[(0,b.jsx)("div",{className:"w-64 border-r border-border bg-card",children:(0,b.jsx)(o,{selectedNode:h,onNodeSelect:a=>{i(a)},refreshKey:j})}),(0,b.jsx)("div",{className:"flex-1 bg-card p-4 overflow-y-auto",children:h?(0,b.jsxs)("div",{className:"space-y-6",children:[(0,b.jsx)(F,{selectedNode:h,onboardingStatus:l,onSwitchToGlobal:()=>{i({scope:"global",label:"Global"})}}),(0,b.jsx)(A,{selectedNode:h}),"global"===h.scope&&(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-foreground",children:"Repositories"}),(0,b.jsx)(J,{})]}),"global"===h.scope&&(0,b.jsx)(_,{}),"global"===h.scope&&(0,b.jsx)(aa.LocalLlmSection,{}),"global"===h.scope&&(0,b.jsx)(az,{}),"global"===h.scope&&(0,b.jsx)(aC,{}),"global"===h.scope&&(0,b.jsx)(aD,{}),"global"===h.scope&&(0,b.jsx)(aG,{}),"repo"===h.scope&&h.owner&&h.repo&&(0,b.jsx)(L,{owner:h.owner,repo:h.repo,onDeleted:()=>{i({scope:"global",label:"Global"}),k(a=>a+1)}})]}):(0,b.jsx)("div",{className:"h-full flex items-center justify-center text-muted-foreground text-sm",children:"Select a node from the left panel"})})]})]})}],40006)}];
6
6
 
7
7
  //# sourceMappingURL=apps_web_src_app_settings_page_tsx_0i6itlb._.js.map