agim-cli 1.2.144 → 1.2.148

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 (611) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/dist/cli-ui/setup-llm.d.ts.map +1 -1
  3. package/dist/cli-ui/setup-llm.js +3 -1
  4. package/dist/cli-ui/setup-llm.js.map +1 -1
  5. package/dist/core/circuit-breaker.d.ts +28 -0
  6. package/dist/core/circuit-breaker.d.ts.map +1 -1
  7. package/dist/core/circuit-breaker.js +45 -0
  8. package/dist/core/circuit-breaker.js.map +1 -1
  9. package/dist/core/intent.d.ts.map +1 -1
  10. package/dist/core/intent.js +3 -1
  11. package/dist/core/intent.js.map +1 -1
  12. package/dist/core/llm/agent-loop.d.ts +9 -1
  13. package/dist/core/llm/agent-loop.d.ts.map +1 -1
  14. package/dist/core/llm/agent-loop.js +80 -1
  15. package/dist/core/llm/agent-loop.js.map +1 -1
  16. package/dist/core/llm/anthropic-provider.d.ts.map +1 -1
  17. package/dist/core/llm/anthropic-provider.js +18 -4
  18. package/dist/core/llm/anthropic-provider.js.map +1 -1
  19. package/dist/core/llm/hallucination-detector.d.ts +33 -0
  20. package/dist/core/llm/hallucination-detector.d.ts.map +1 -0
  21. package/dist/core/llm/hallucination-detector.js +103 -0
  22. package/dist/core/llm/hallucination-detector.js.map +1 -0
  23. package/dist/core/llm/imhub-dispatcher.d.ts.map +1 -1
  24. package/dist/core/llm/imhub-dispatcher.js +7 -0
  25. package/dist/core/llm/imhub-dispatcher.js.map +1 -1
  26. package/dist/core/llm/provider-base.d.ts +9 -0
  27. package/dist/core/llm/provider-base.d.ts.map +1 -1
  28. package/dist/core/llm/provider-base.js.map +1 -1
  29. package/dist/core/memory-distill.d.ts.map +1 -1
  30. package/dist/core/memory-distill.js +18 -3
  31. package/dist/core/memory-distill.js.map +1 -1
  32. package/dist/core/memory.d.ts +14 -0
  33. package/dist/core/memory.d.ts.map +1 -1
  34. package/dist/core/memory.js +39 -0
  35. package/dist/core/memory.js.map +1 -1
  36. package/dist/core/message-sink.d.ts +6 -0
  37. package/dist/core/message-sink.d.ts.map +1 -1
  38. package/dist/core/message-sink.js +18 -3
  39. package/dist/core/message-sink.js.map +1 -1
  40. package/dist/core/outbox.d.ts +30 -2
  41. package/dist/core/outbox.d.ts.map +1 -1
  42. package/dist/core/outbox.js +102 -10
  43. package/dist/core/outbox.js.map +1 -1
  44. package/dist/core/reminders.d.ts.map +1 -1
  45. package/dist/core/reminders.js +11 -1
  46. package/dist/core/reminders.js.map +1 -1
  47. package/dist/core/router.d.ts.map +1 -1
  48. package/dist/core/router.js +16 -4
  49. package/dist/core/router.js.map +1 -1
  50. package/dist/core/schedule.d.ts +18 -0
  51. package/dist/core/schedule.d.ts.map +1 -1
  52. package/dist/core/schedule.js +80 -17
  53. package/dist/core/schedule.js.map +1 -1
  54. package/dist/core/sensitive-paths.d.ts.map +1 -1
  55. package/dist/core/sensitive-paths.js +53 -9
  56. package/dist/core/sensitive-paths.js.map +1 -1
  57. package/dist/core/skills/builtin/ECC_LICENSE +21 -0
  58. package/dist/core/skills/builtin/ECC_NOTICE.md +22 -0
  59. package/dist/core/skills/builtin/accessibility/SKILL.md +146 -0
  60. package/dist/core/skills/builtin/agent-eval/SKILL.md +145 -0
  61. package/dist/core/skills/builtin/agent-harness-construction/SKILL.md +73 -0
  62. package/dist/core/skills/builtin/agent-introspection-debugging/SKILL.md +153 -0
  63. package/dist/core/skills/builtin/agentic-engineering/SKILL.md +63 -0
  64. package/dist/core/skills/builtin/ai-first-engineering/SKILL.md +51 -0
  65. package/dist/core/skills/builtin/ai-regression-testing/SKILL.md +385 -0
  66. package/dist/core/skills/builtin/android-clean-architecture/SKILL.md +339 -0
  67. package/dist/core/skills/builtin/angular-developer/SKILL.md +154 -0
  68. package/dist/core/skills/builtin/angular-developer/references/angular-animations.md +160 -0
  69. package/dist/core/skills/builtin/angular-developer/references/angular-aria.md +410 -0
  70. package/dist/core/skills/builtin/angular-developer/references/cli.md +86 -0
  71. package/dist/core/skills/builtin/angular-developer/references/component-harnesses.md +59 -0
  72. package/dist/core/skills/builtin/angular-developer/references/component-styling.md +91 -0
  73. package/dist/core/skills/builtin/angular-developer/references/components.md +117 -0
  74. package/dist/core/skills/builtin/angular-developer/references/creating-services.md +97 -0
  75. package/dist/core/skills/builtin/angular-developer/references/data-resolvers.md +69 -0
  76. package/dist/core/skills/builtin/angular-developer/references/define-routes.md +67 -0
  77. package/dist/core/skills/builtin/angular-developer/references/defining-providers.md +72 -0
  78. package/dist/core/skills/builtin/angular-developer/references/di-fundamentals.md +120 -0
  79. package/dist/core/skills/builtin/angular-developer/references/e2e-testing.md +56 -0
  80. package/dist/core/skills/builtin/angular-developer/references/effects.md +83 -0
  81. package/dist/core/skills/builtin/angular-developer/references/hierarchical-injectors.md +43 -0
  82. package/dist/core/skills/builtin/angular-developer/references/host-elements.md +80 -0
  83. package/dist/core/skills/builtin/angular-developer/references/injection-context.md +63 -0
  84. package/dist/core/skills/builtin/angular-developer/references/inputs.md +101 -0
  85. package/dist/core/skills/builtin/angular-developer/references/linked-signal.md +59 -0
  86. package/dist/core/skills/builtin/angular-developer/references/loading-strategies.md +61 -0
  87. package/dist/core/skills/builtin/angular-developer/references/mcp.md +108 -0
  88. package/dist/core/skills/builtin/angular-developer/references/navigate-to-routes.md +69 -0
  89. package/dist/core/skills/builtin/angular-developer/references/outputs.md +86 -0
  90. package/dist/core/skills/builtin/angular-developer/references/reactive-forms.md +122 -0
  91. package/dist/core/skills/builtin/angular-developer/references/rendering-strategies.md +44 -0
  92. package/dist/core/skills/builtin/angular-developer/references/resource.md +77 -0
  93. package/dist/core/skills/builtin/angular-developer/references/route-animations.md +56 -0
  94. package/dist/core/skills/builtin/angular-developer/references/route-guards.md +52 -0
  95. package/dist/core/skills/builtin/angular-developer/references/router-lifecycle.md +45 -0
  96. package/dist/core/skills/builtin/angular-developer/references/router-testing.md +87 -0
  97. package/dist/core/skills/builtin/angular-developer/references/show-routes-with-outlets.md +68 -0
  98. package/dist/core/skills/builtin/angular-developer/references/signal-forms.md +795 -0
  99. package/dist/core/skills/builtin/angular-developer/references/signals-overview.md +94 -0
  100. package/dist/core/skills/builtin/angular-developer/references/tailwind-css.md +69 -0
  101. package/dist/core/skills/builtin/angular-developer/references/template-driven-forms.md +114 -0
  102. package/dist/core/skills/builtin/angular-developer/references/testing-fundamentals.md +65 -0
  103. package/dist/core/skills/builtin/api-connector-builder/SKILL.md +120 -0
  104. package/dist/core/skills/builtin/api-design/SKILL.md +523 -0
  105. package/dist/core/skills/builtin/architecture-decision-records/SKILL.md +179 -0
  106. package/dist/core/skills/builtin/article-writing/SKILL.md +79 -0
  107. package/dist/core/skills/builtin/automation-audit-ops/SKILL.md +142 -0
  108. package/dist/core/skills/builtin/autonomous-agent-harness/SKILL.md +273 -0
  109. package/dist/core/skills/builtin/autonomous-loops/SKILL.md +610 -0
  110. package/dist/core/skills/builtin/backend-patterns/SKILL.md +561 -0
  111. package/dist/core/skills/builtin/benchmark/SKILL.md +93 -0
  112. package/dist/core/skills/builtin/benchmark-optimization-loop/SKILL.md +69 -0
  113. package/dist/core/skills/builtin/blueprint/SKILL.md +105 -0
  114. package/dist/core/skills/builtin/browser-qa/SKILL.md +87 -0
  115. package/dist/core/skills/builtin/bun-runtime/SKILL.md +84 -0
  116. package/dist/core/skills/builtin/cisco-ios-patterns/SKILL.md +163 -0
  117. package/dist/core/skills/builtin/claude-devfleet/SKILL.md +111 -0
  118. package/dist/core/skills/builtin/click-path-audit/SKILL.md +244 -0
  119. package/dist/core/skills/builtin/clickhouse-io/SKILL.md +439 -0
  120. package/dist/core/skills/builtin/code-tour/SKILL.md +236 -0
  121. package/dist/core/skills/builtin/codebase-onboarding/SKILL.md +233 -0
  122. package/dist/core/skills/builtin/codehealth-mcp/SKILL.md +166 -0
  123. package/dist/core/skills/builtin/coding-standards/SKILL.md +550 -0
  124. package/dist/core/skills/builtin/compose-multiplatform-patterns/SKILL.md +299 -0
  125. package/dist/core/skills/builtin/config-gc/SKILL.md +119 -0
  126. package/dist/core/skills/builtin/content-hash-cache-pattern/SKILL.md +161 -0
  127. package/dist/core/skills/builtin/context-budget/SKILL.md +135 -0
  128. package/dist/core/skills/builtin/continuous-agent-loop/SKILL.md +45 -0
  129. package/dist/core/skills/builtin/continuous-learning/SKILL.md +131 -0
  130. package/dist/core/skills/builtin/continuous-learning/config.json +18 -0
  131. package/dist/core/skills/builtin/continuous-learning/evaluate-session.sh +69 -0
  132. package/dist/core/skills/builtin/continuous-learning-v2/SKILL.md +360 -0
  133. package/dist/core/skills/builtin/continuous-learning-v2/agents/observer-loop.sh +335 -0
  134. package/dist/core/skills/builtin/continuous-learning-v2/agents/observer.md +198 -0
  135. package/dist/core/skills/builtin/continuous-learning-v2/agents/session-guardian.sh +150 -0
  136. package/dist/core/skills/builtin/continuous-learning-v2/agents/start-observer.sh +248 -0
  137. package/dist/core/skills/builtin/continuous-learning-v2/config.json +8 -0
  138. package/dist/core/skills/builtin/continuous-learning-v2/hooks/observe.sh +498 -0
  139. package/dist/core/skills/builtin/continuous-learning-v2/scripts/detect-project.sh +322 -0
  140. package/dist/core/skills/builtin/continuous-learning-v2/scripts/instinct-cli.py +1914 -0
  141. package/dist/core/skills/builtin/continuous-learning-v2/scripts/lib/homunculus-dir.sh +31 -0
  142. package/dist/core/skills/builtin/continuous-learning-v2/scripts/migrate-homunculus.sh +62 -0
  143. package/dist/core/skills/builtin/continuous-learning-v2/scripts/test_parse_instinct.py +1045 -0
  144. package/dist/core/skills/builtin/cost-aware-llm-pipeline/SKILL.md +183 -0
  145. package/dist/core/skills/builtin/cost-tracking/SKILL.md +147 -0
  146. package/dist/core/skills/builtin/council/SKILL.md +203 -0
  147. package/dist/core/skills/builtin/cpp-coding-standards/SKILL.md +723 -0
  148. package/dist/core/skills/builtin/cpp-testing/SKILL.md +324 -0
  149. package/dist/core/skills/builtin/crosspost/SKILL.md +111 -0
  150. package/dist/core/skills/builtin/csharp-testing/SKILL.md +321 -0
  151. package/dist/core/skills/builtin/customs-trade-compliance/SKILL.md +263 -0
  152. package/dist/core/skills/builtin/dart-flutter-patterns/SKILL.md +563 -0
  153. package/dist/core/skills/builtin/dashboard-builder/SKILL.md +108 -0
  154. package/dist/core/skills/builtin/data-scraper-agent/SKILL.md +764 -0
  155. package/dist/core/skills/builtin/data-throughput-accelerator/SKILL.md +72 -0
  156. package/dist/core/skills/builtin/database-migrations/SKILL.md +429 -0
  157. package/dist/core/skills/builtin/deep-research/SKILL.md +159 -0
  158. package/dist/core/skills/builtin/defi-amm-security/SKILL.md +166 -0
  159. package/dist/core/skills/builtin/deployment-patterns/SKILL.md +427 -0
  160. package/dist/core/skills/builtin/design-system/SKILL.md +82 -0
  161. package/dist/core/skills/builtin/django-celery/SKILL.md +457 -0
  162. package/dist/core/skills/builtin/django-patterns/SKILL.md +734 -0
  163. package/dist/core/skills/builtin/django-security/SKILL.md +593 -0
  164. package/dist/core/skills/builtin/django-tdd/SKILL.md +729 -0
  165. package/dist/core/skills/builtin/django-verification/SKILL.md +469 -0
  166. package/dist/core/skills/builtin/dmux-workflows/SKILL.md +191 -0
  167. package/dist/core/skills/builtin/docker-patterns/SKILL.md +364 -0
  168. package/dist/core/skills/builtin/documentation-lookup/SKILL.md +90 -0
  169. package/dist/core/skills/builtin/dotnet-patterns/SKILL.md +321 -0
  170. package/dist/core/skills/builtin/dynamic-workflow-mode/SKILL.md +123 -0
  171. package/dist/core/skills/builtin/e2e-testing/SKILL.md +326 -0
  172. package/dist/core/skills/builtin/email-ops/SKILL.md +121 -0
  173. package/dist/core/skills/builtin/energy-procurement/SKILL.md +228 -0
  174. package/dist/core/skills/builtin/enterprise-agent-ops/SKILL.md +50 -0
  175. package/dist/core/skills/builtin/error-handling/SKILL.md +376 -0
  176. package/dist/core/skills/builtin/eval-harness/SKILL.md +270 -0
  177. package/dist/core/skills/builtin/evm-token-decimals/SKILL.md +130 -0
  178. package/dist/core/skills/builtin/exa-search/SKILL.md +107 -0
  179. package/dist/core/skills/builtin/fal-ai-media/SKILL.md +288 -0
  180. package/dist/core/skills/builtin/fastapi-patterns/SKILL.md +513 -0
  181. package/dist/core/skills/builtin/finance-billing-ops/SKILL.md +127 -0
  182. package/dist/core/skills/builtin/flox-environments/SKILL.md +496 -0
  183. package/dist/core/skills/builtin/flutter-dart-code-review/SKILL.md +435 -0
  184. package/dist/core/skills/builtin/foundation-models-on-device/SKILL.md +243 -0
  185. package/dist/core/skills/builtin/frontend-a11y/SKILL.md +445 -0
  186. package/dist/core/skills/builtin/frontend-design-direction/SKILL.md +92 -0
  187. package/dist/core/skills/builtin/frontend-patterns/SKILL.md +656 -0
  188. package/dist/core/skills/builtin/frontend-slides/SKILL.md +184 -0
  189. package/dist/core/skills/builtin/frontend-slides/STYLE_PRESETS.md +330 -0
  190. package/dist/core/skills/builtin/frontend-slides/animation-patterns.md +122 -0
  191. package/dist/core/skills/builtin/frontend-slides/html-template.md +419 -0
  192. package/dist/core/skills/builtin/frontend-slides/scripts/export-pdf.sh +418 -0
  193. package/dist/core/skills/builtin/frontend-slides/scripts/extract-pptx.py +96 -0
  194. package/dist/core/skills/builtin/frontend-slides/viewport-base.css +153 -0
  195. package/dist/core/skills/builtin/fsharp-testing/SKILL.md +280 -0
  196. package/dist/core/skills/builtin/gan-style-harness/SKILL.md +278 -0
  197. package/dist/core/skills/builtin/gateguard/SKILL.md +132 -0
  198. package/dist/core/skills/builtin/git-workflow/SKILL.md +715 -0
  199. package/dist/core/skills/builtin/github-ops/SKILL.md +144 -0
  200. package/dist/core/skills/builtin/golang-patterns/SKILL.md +674 -0
  201. package/dist/core/skills/builtin/golang-testing/SKILL.md +720 -0
  202. package/dist/core/skills/builtin/healthcare-cdss-patterns/SKILL.md +245 -0
  203. package/dist/core/skills/builtin/healthcare-emr-patterns/SKILL.md +159 -0
  204. package/dist/core/skills/builtin/healthcare-eval-harness/SKILL.md +207 -0
  205. package/dist/core/skills/builtin/healthcare-phi-compliance/SKILL.md +145 -0
  206. package/dist/core/skills/builtin/hermes-imports/SKILL.md +88 -0
  207. package/dist/core/skills/builtin/hexagonal-architecture/SKILL.md +276 -0
  208. package/dist/core/skills/builtin/hipaa-compliance/SKILL.md +78 -0
  209. package/dist/core/skills/builtin/hookify-rules/SKILL.md +128 -0
  210. package/dist/core/skills/builtin/inherit-legacy-style/SKILL.md +156 -0
  211. package/dist/core/skills/builtin/intent-driven-development/SKILL.md +360 -0
  212. package/dist/core/skills/builtin/inventory-demand-planning/SKILL.md +247 -0
  213. package/dist/core/skills/builtin/ios-icon-gen/SKILL.md +157 -0
  214. package/dist/core/skills/builtin/ios-icon-gen/scripts/generate_icons.swift +258 -0
  215. package/dist/core/skills/builtin/ios-icon-gen/scripts/iconify_gen.sh +235 -0
  216. package/dist/core/skills/builtin/iterative-retrieval/SKILL.md +211 -0
  217. package/dist/core/skills/builtin/java-coding-standards/SKILL.md +383 -0
  218. package/dist/core/skills/builtin/jira-integration/SKILL.md +302 -0
  219. package/dist/core/skills/builtin/jpa-patterns/SKILL.md +151 -0
  220. package/dist/core/skills/builtin/knowledge-ops/SKILL.md +154 -0
  221. package/dist/core/skills/builtin/kotlin-coroutines-flows/SKILL.md +284 -0
  222. package/dist/core/skills/builtin/kotlin-exposed-patterns/SKILL.md +719 -0
  223. package/dist/core/skills/builtin/kotlin-ktor-patterns/SKILL.md +689 -0
  224. package/dist/core/skills/builtin/kotlin-patterns/SKILL.md +711 -0
  225. package/dist/core/skills/builtin/kotlin-testing/SKILL.md +824 -0
  226. package/dist/core/skills/builtin/kubernetes-patterns/SKILL.md +755 -0
  227. package/dist/core/skills/builtin/laravel-patterns/SKILL.md +415 -0
  228. package/dist/core/skills/builtin/laravel-plugin-discovery/SKILL.md +229 -0
  229. package/dist/core/skills/builtin/laravel-security/SKILL.md +947 -0
  230. package/dist/core/skills/builtin/laravel-tdd/SKILL.md +674 -0
  231. package/dist/core/skills/builtin/laravel-verification/SKILL.md +179 -0
  232. package/dist/core/skills/builtin/latency-critical-systems/SKILL.md +73 -0
  233. package/dist/core/skills/builtin/lead-intelligence/SKILL.md +321 -0
  234. package/dist/core/skills/builtin/lead-intelligence/agents/enrichment-agent.md +85 -0
  235. package/dist/core/skills/builtin/lead-intelligence/agents/mutual-mapper.md +75 -0
  236. package/dist/core/skills/builtin/lead-intelligence/agents/outreach-drafter.md +98 -0
  237. package/dist/core/skills/builtin/lead-intelligence/agents/signal-scorer.md +60 -0
  238. package/dist/core/skills/builtin/liquid-glass-design/SKILL.md +279 -0
  239. package/dist/core/skills/builtin/llm-trading-agent-security/SKILL.md +146 -0
  240. package/dist/core/skills/builtin/logistics-exception-management/SKILL.md +222 -0
  241. package/dist/core/skills/builtin/make-interfaces-feel-better/SKILL.md +151 -0
  242. package/dist/core/skills/builtin/market-research/SKILL.md +75 -0
  243. package/dist/core/skills/builtin/marketing-campaign/SKILL.md +113 -0
  244. package/dist/core/skills/builtin/mcp-server-patterns/SKILL.md +69 -0
  245. package/dist/core/skills/builtin/messages-ops/SKILL.md +104 -0
  246. package/dist/core/skills/builtin/mle-workflow/SKILL.md +346 -0
  247. package/dist/core/skills/builtin/motion-advanced/SKILL.md +596 -0
  248. package/dist/core/skills/builtin/motion-foundations/SKILL.md +299 -0
  249. package/dist/core/skills/builtin/motion-patterns/SKILL.md +434 -0
  250. package/dist/core/skills/builtin/motion-ui/SKILL.md +575 -0
  251. package/dist/core/skills/builtin/mysql-patterns/SKILL.md +412 -0
  252. package/dist/core/skills/builtin/nanoclaw-repl/SKILL.md +33 -0
  253. package/dist/core/skills/builtin/nestjs-patterns/SKILL.md +230 -0
  254. package/dist/core/skills/builtin/netmiko-ssh-automation/SKILL.md +173 -0
  255. package/dist/core/skills/builtin/network-bgp-diagnostics/SKILL.md +167 -0
  256. package/dist/core/skills/builtin/network-config-validation/SKILL.md +210 -0
  257. package/dist/core/skills/builtin/network-interface-health/SKILL.md +152 -0
  258. package/dist/core/skills/builtin/nextjs-turbopack/SKILL.md +57 -0
  259. package/dist/core/skills/builtin/nodejs-keccak256/SKILL.md +102 -0
  260. package/dist/core/skills/builtin/nutrient-document-processing/SKILL.md +167 -0
  261. package/dist/core/skills/builtin/nuxt4-patterns/SKILL.md +100 -0
  262. package/dist/core/skills/builtin/openclaw-persona-forge/SKILL.md +288 -0
  263. package/dist/core/skills/builtin/openclaw-persona-forge/gacha.py +224 -0
  264. package/dist/core/skills/builtin/openclaw-persona-forge/gacha.sh +5 -0
  265. package/dist/core/skills/builtin/openclaw-persona-forge/references/avatar-style.md +124 -0
  266. package/dist/core/skills/builtin/openclaw-persona-forge/references/boundary-rules.md +53 -0
  267. package/dist/core/skills/builtin/openclaw-persona-forge/references/error-handling.md +53 -0
  268. package/dist/core/skills/builtin/openclaw-persona-forge/references/identity-tension.md +48 -0
  269. package/dist/core/skills/builtin/openclaw-persona-forge/references/naming-system.md +39 -0
  270. package/dist/core/skills/builtin/openclaw-persona-forge/references/output-template.md +166 -0
  271. package/dist/core/skills/builtin/opensource-pipeline/SKILL.md +255 -0
  272. package/dist/core/skills/builtin/orch-add-feature/SKILL.md +44 -0
  273. package/dist/core/skills/builtin/orch-build-mvp/SKILL.md +48 -0
  274. package/dist/core/skills/builtin/orch-change-feature/SKILL.md +42 -0
  275. package/dist/core/skills/builtin/orch-fix-defect/SKILL.md +42 -0
  276. package/dist/core/skills/builtin/orch-pipeline/SKILL.md +120 -0
  277. package/dist/core/skills/builtin/orch-refine-code/SKILL.md +43 -0
  278. package/dist/core/skills/builtin/parallel-execution-optimizer/SKILL.md +72 -0
  279. package/dist/core/skills/builtin/perl-patterns/SKILL.md +504 -0
  280. package/dist/core/skills/builtin/perl-security/SKILL.md +503 -0
  281. package/dist/core/skills/builtin/perl-testing/SKILL.md +475 -0
  282. package/dist/core/skills/builtin/plan-orchestrate/SKILL.md +262 -0
  283. package/dist/core/skills/builtin/plankton-code-quality/SKILL.md +236 -0
  284. package/dist/core/skills/builtin/postgres-patterns/SKILL.md +147 -0
  285. package/dist/core/skills/builtin/prediction-market-oracle-research/SKILL.md +63 -0
  286. package/dist/core/skills/builtin/prediction-market-risk-review/SKILL.md +60 -0
  287. package/dist/core/skills/builtin/prisma-patterns/SKILL.md +371 -0
  288. package/dist/core/skills/builtin/product-capability/SKILL.md +141 -0
  289. package/dist/core/skills/builtin/product-lens/SKILL.md +92 -0
  290. package/dist/core/skills/builtin/production-audit/SKILL.md +206 -0
  291. package/dist/core/skills/builtin/production-scheduling/SKILL.md +238 -0
  292. package/dist/core/skills/builtin/prompt-optimizer/SKILL.md +398 -0
  293. package/dist/core/skills/builtin/python-patterns/SKILL.md +750 -0
  294. package/dist/core/skills/builtin/python-testing/SKILL.md +816 -0
  295. package/dist/core/skills/builtin/pytorch-patterns/SKILL.md +396 -0
  296. package/dist/core/skills/builtin/quality-nonconformance/SKILL.md +260 -0
  297. package/dist/core/skills/builtin/quarkus-patterns/SKILL.md +722 -0
  298. package/dist/core/skills/builtin/quarkus-security/SKILL.md +467 -0
  299. package/dist/core/skills/builtin/quarkus-tdd/SKILL.md +811 -0
  300. package/dist/core/skills/builtin/quarkus-verification/SKILL.md +479 -0
  301. package/dist/core/skills/builtin/ralphinho-rfc-pipeline/SKILL.md +67 -0
  302. package/dist/core/skills/builtin/react-patterns/SKILL.md +341 -0
  303. package/dist/core/skills/builtin/react-performance/SKILL.md +574 -0
  304. package/dist/core/skills/builtin/react-testing/SKILL.md +423 -0
  305. package/dist/core/skills/builtin/recsys-pipeline-architect/SKILL.md +114 -0
  306. package/dist/core/skills/builtin/recursive-decision-ledger/SKILL.md +79 -0
  307. package/dist/core/skills/builtin/redis-patterns/SKILL.md +403 -0
  308. package/dist/core/skills/builtin/regex-vs-llm-structured-text/SKILL.md +220 -0
  309. package/dist/core/skills/builtin/repo-scan/SKILL.md +78 -0
  310. package/dist/core/skills/builtin/research-ops/SKILL.md +112 -0
  311. package/dist/core/skills/builtin/returns-reverse-logistics/SKILL.md +240 -0
  312. package/dist/core/skills/builtin/rules-distill/SKILL.md +264 -0
  313. package/dist/core/skills/builtin/rules-distill/scripts/scan-rules.sh +58 -0
  314. package/dist/core/skills/builtin/rules-distill/scripts/scan-skills.sh +129 -0
  315. package/dist/core/skills/builtin/rust-patterns/SKILL.md +499 -0
  316. package/dist/core/skills/builtin/rust-testing/SKILL.md +500 -0
  317. package/dist/core/skills/builtin/safety-guard/SKILL.md +75 -0
  318. package/dist/core/skills/builtin/santa-method/SKILL.md +306 -0
  319. package/dist/core/skills/builtin/scientific-db-pubmed-database/SKILL.md +175 -0
  320. package/dist/core/skills/builtin/scientific-db-uspto-database/SKILL.md +177 -0
  321. package/dist/core/skills/builtin/scientific-pkg-gget/SKILL.md +166 -0
  322. package/dist/core/skills/builtin/scientific-thinking-literature-review/SKILL.md +192 -0
  323. package/dist/core/skills/builtin/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
  324. package/dist/core/skills/builtin/search-first/SKILL.md +182 -0
  325. package/dist/core/skills/builtin/security-bounty-hunter/SKILL.md +99 -0
  326. package/dist/core/skills/builtin/security-review/SKILL.md +503 -0
  327. package/dist/core/skills/builtin/security-review/cloud-infrastructure-security.md +361 -0
  328. package/dist/core/skills/builtin/security-scan/SKILL.md +165 -0
  329. package/dist/core/skills/builtin/seo/SKILL.md +154 -0
  330. package/dist/core/skills/builtin/skill-comply/SKILL.md +58 -0
  331. package/dist/core/skills/builtin/skill-comply/fixtures/compliant_trace.jsonl +5 -0
  332. package/dist/core/skills/builtin/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
  333. package/dist/core/skills/builtin/skill-comply/fixtures/tdd_spec.yaml +44 -0
  334. package/dist/core/skills/builtin/skill-comply/prompts/classifier.md +24 -0
  335. package/dist/core/skills/builtin/skill-comply/prompts/scenario_generator.md +62 -0
  336. package/dist/core/skills/builtin/skill-comply/prompts/spec_generator.md +42 -0
  337. package/dist/core/skills/builtin/skill-comply/pyproject.toml +15 -0
  338. package/dist/core/skills/builtin/skill-comply/scripts/__init__.py +0 -0
  339. package/dist/core/skills/builtin/skill-comply/scripts/classifier.py +85 -0
  340. package/dist/core/skills/builtin/skill-comply/scripts/grader.py +124 -0
  341. package/dist/core/skills/builtin/skill-comply/scripts/parser.py +107 -0
  342. package/dist/core/skills/builtin/skill-comply/scripts/report.py +170 -0
  343. package/dist/core/skills/builtin/skill-comply/scripts/run.py +127 -0
  344. package/dist/core/skills/builtin/skill-comply/scripts/runner.py +186 -0
  345. package/dist/core/skills/builtin/skill-comply/scripts/scenario_generator.py +70 -0
  346. package/dist/core/skills/builtin/skill-comply/scripts/spec_generator.py +72 -0
  347. package/dist/core/skills/builtin/skill-comply/scripts/utils.py +13 -0
  348. package/dist/core/skills/builtin/skill-comply/tests/test_grader.py +197 -0
  349. package/dist/core/skills/builtin/skill-comply/tests/test_parser.py +90 -0
  350. package/dist/core/skills/builtin/skill-comply/tests/test_runner.py +172 -0
  351. package/dist/core/skills/builtin/skill-scout/SKILL.md +140 -0
  352. package/dist/core/skills/builtin/skill-stocktake/SKILL.md +194 -0
  353. package/dist/core/skills/builtin/skill-stocktake/scripts/quick-diff.sh +87 -0
  354. package/dist/core/skills/builtin/skill-stocktake/scripts/save-results.sh +56 -0
  355. package/dist/core/skills/builtin/skill-stocktake/scripts/scan.sh +170 -0
  356. package/dist/core/skills/builtin/springboot-patterns/SKILL.md +314 -0
  357. package/dist/core/skills/builtin/springboot-security/SKILL.md +272 -0
  358. package/dist/core/skills/builtin/springboot-tdd/SKILL.md +158 -0
  359. package/dist/core/skills/builtin/springboot-verification/SKILL.md +231 -0
  360. package/dist/core/skills/builtin/strategic-compact/SKILL.md +135 -0
  361. package/dist/core/skills/builtin/swift-actor-persistence/SKILL.md +143 -0
  362. package/dist/core/skills/builtin/swift-concurrency-6-2/SKILL.md +216 -0
  363. package/dist/core/skills/builtin/swift-protocol-di-testing/SKILL.md +190 -0
  364. package/dist/core/skills/builtin/swiftui-patterns/SKILL.md +259 -0
  365. package/dist/core/skills/builtin/tdd-workflow/SKILL.md +463 -0
  366. package/dist/core/skills/builtin/team-agent-orchestration/SKILL.md +110 -0
  367. package/dist/core/skills/builtin/team-builder/SKILL.md +168 -0
  368. package/dist/core/skills/builtin/terminal-ops/SKILL.md +109 -0
  369. package/dist/core/skills/builtin/tinystruct-patterns/SKILL.md +203 -0
  370. package/dist/core/skills/builtin/tinystruct-patterns/references/architecture.md +90 -0
  371. package/dist/core/skills/builtin/tinystruct-patterns/references/data-handling.md +60 -0
  372. package/dist/core/skills/builtin/tinystruct-patterns/references/database.md +99 -0
  373. package/dist/core/skills/builtin/tinystruct-patterns/references/routing.md +64 -0
  374. package/dist/core/skills/builtin/tinystruct-patterns/references/system-usage.md +97 -0
  375. package/dist/core/skills/builtin/tinystruct-patterns/references/testing.md +72 -0
  376. package/dist/core/skills/builtin/token-budget-advisor/SKILL.md +133 -0
  377. package/dist/core/skills/builtin/ui-demo/SKILL.md +465 -0
  378. package/dist/core/skills/builtin/ui-to-vue/SKILL.md +134 -0
  379. package/dist/core/skills/builtin/uncloud/SKILL.md +343 -0
  380. package/dist/core/skills/builtin/unified-notifications-ops/SKILL.md +187 -0
  381. package/dist/core/skills/builtin/verification-loop/SKILL.md +126 -0
  382. package/dist/core/skills/builtin/video-editing/SKILL.md +310 -0
  383. package/dist/core/skills/builtin/videodb/SKILL.md +374 -0
  384. package/dist/core/skills/builtin/videodb/reference/api-reference.md +550 -0
  385. package/dist/core/skills/builtin/videodb/reference/capture-reference.md +407 -0
  386. package/dist/core/skills/builtin/videodb/reference/capture.md +101 -0
  387. package/dist/core/skills/builtin/videodb/reference/editor.md +443 -0
  388. package/dist/core/skills/builtin/videodb/reference/generative.md +331 -0
  389. package/dist/core/skills/builtin/videodb/reference/rtstream-reference.md +564 -0
  390. package/dist/core/skills/builtin/videodb/reference/rtstream.md +65 -0
  391. package/dist/core/skills/builtin/videodb/reference/search.md +230 -0
  392. package/dist/core/skills/builtin/videodb/reference/streaming.md +406 -0
  393. package/dist/core/skills/builtin/videodb/reference/use-cases.md +118 -0
  394. package/dist/core/skills/builtin/videodb/scripts/ws_listener.py +282 -0
  395. package/dist/core/skills/builtin/visa-doc-translate/README.md +86 -0
  396. package/dist/core/skills/builtin/visa-doc-translate/SKILL.md +117 -0
  397. package/dist/core/skills/builtin/vite-patterns/SKILL.md +449 -0
  398. package/dist/core/skills/builtin/windows-desktop-e2e/SKILL.md +887 -0
  399. package/dist/core/skills/builtin/x-api/SKILL.md +234 -0
  400. package/dist/core/skills/loader.js +11 -0
  401. package/dist/core/skills/loader.js.map +1 -1
  402. package/dist/core/types.d.ts +6 -0
  403. package/dist/core/types.d.ts.map +1 -1
  404. package/dist/plugins/agents/native/index.d.ts +47 -8
  405. package/dist/plugins/agents/native/index.d.ts.map +1 -1
  406. package/dist/plugins/agents/native/index.js +253 -102
  407. package/dist/plugins/agents/native/index.js.map +1 -1
  408. package/dist/plugins/agents/native/tool-registry.d.ts +33 -0
  409. package/dist/plugins/agents/native/tool-registry.d.ts.map +1 -0
  410. package/dist/plugins/agents/native/tool-registry.js +82 -0
  411. package/dist/plugins/agents/native/tool-registry.js.map +1 -0
  412. package/dist/plugins/messengers/dingtalk/dingtalk-client.d.ts.map +1 -1
  413. package/dist/plugins/messengers/dingtalk/dingtalk-client.js +11 -11
  414. package/dist/plugins/messengers/dingtalk/dingtalk-client.js.map +1 -1
  415. package/dist/plugins/messengers/feishu/feishu-adapter.d.ts.map +1 -1
  416. package/dist/plugins/messengers/feishu/feishu-adapter.js +9 -5
  417. package/dist/plugins/messengers/feishu/feishu-adapter.js.map +1 -1
  418. package/dist/plugins/messengers/wechat/ilink-adapter.d.ts.map +1 -1
  419. package/dist/plugins/messengers/wechat/ilink-adapter.js +11 -1
  420. package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -1
  421. package/dist/web/public/assets/{a2a-DczMMkbl.js → a2a-Cll3P4QN.js} +2 -2
  422. package/dist/web/public/assets/{a2a-DczMMkbl.js.map → a2a-Cll3P4QN.js.map} +1 -1
  423. package/dist/web/public/assets/{activity-cbLHkzca.js → activity-B7T7YFlD.js} +2 -2
  424. package/dist/web/public/assets/{activity-cbLHkzca.js.map → activity-B7T7YFlD.js.map} +1 -1
  425. package/dist/web/public/assets/{admins-C-YsGMj7.js → admins-CN7P018S.js} +2 -2
  426. package/dist/web/public/assets/{admins-C-YsGMj7.js.map → admins-CN7P018S.js.map} +1 -1
  427. package/dist/web/public/assets/{agents-BWfov_1-.js → agents-Bqgq7GBF.js} +2 -2
  428. package/dist/web/public/assets/{agents-BWfov_1-.js.map → agents-Bqgq7GBF.js.map} +1 -1
  429. package/dist/web/public/assets/{approvals-HSssmXKS.js → approvals-C8IUJQ_A.js} +2 -2
  430. package/dist/web/public/assets/{approvals-HSssmXKS.js.map → approvals-C8IUJQ_A.js.map} +1 -1
  431. package/dist/web/public/assets/{arrow-down-BXvC8Al2.js → arrow-down-SLWKqtDc.js} +2 -2
  432. package/dist/web/public/assets/{arrow-down-BXvC8Al2.js.map → arrow-down-SLWKqtDc.js.map} +1 -1
  433. package/dist/web/public/assets/{arrow-up-63xELY5Q.js → arrow-up-BOADc9ce.js} +2 -2
  434. package/dist/web/public/assets/{arrow-up-63xELY5Q.js.map → arrow-up-BOADc9ce.js.map} +1 -1
  435. package/dist/web/public/assets/{asks-COLEFOvK.js → asks-C-j-DypC.js} +2 -2
  436. package/dist/web/public/assets/{asks-COLEFOvK.js.map → asks-C-j-DypC.js.map} +1 -1
  437. package/dist/web/public/assets/{audit-D4ZEiZub.js → audit-DQb-RuXh.js} +2 -2
  438. package/dist/web/public/assets/{audit-D4ZEiZub.js.map → audit-DQb-RuXh.js.map} +1 -1
  439. package/dist/web/public/assets/{bell-Cg2Bvv06.js → bell-CV88-ul6.js} +2 -2
  440. package/dist/web/public/assets/{bell-Cg2Bvv06.js.map → bell-CV88-ul6.js.map} +1 -1
  441. package/dist/web/public/assets/{bgjobs-CEjCzwtd.js → bgjobs-CDrK0d-W.js} +2 -2
  442. package/dist/web/public/assets/{bgjobs-CEjCzwtd.js.map → bgjobs-CDrK0d-W.js.map} +1 -1
  443. package/dist/web/public/assets/{brain-euvl6F6C.js → brain-B7HtSOQU.js} +2 -2
  444. package/dist/web/public/assets/{brain-euvl6F6C.js.map → brain-B7HtSOQU.js.map} +1 -1
  445. package/dist/web/public/assets/{briefcase-DPWLbCnA.js → briefcase-mdzuIa__.js} +2 -2
  446. package/dist/web/public/assets/{briefcase-DPWLbCnA.js.map → briefcase-mdzuIa__.js.map} +1 -1
  447. package/dist/web/public/assets/{browser-ponyfill-BUutOaRz.js → browser-ponyfill-DBWdeCTC.js} +2 -2
  448. package/dist/web/public/assets/{browser-ponyfill-BUutOaRz.js.map → browser-ponyfill-DBWdeCTC.js.map} +1 -1
  449. package/dist/web/public/assets/{chat-Dz9kfaxH.js → chat-CSjtY2rN.js} +3 -3
  450. package/dist/web/public/assets/{chat-Dz9kfaxH.js.map → chat-CSjtY2rN.js.map} +1 -1
  451. package/dist/web/public/assets/{chevron-left-BeIh5thq.js → chevron-left-uSfPn636.js} +2 -2
  452. package/dist/web/public/assets/{chevron-left-BeIh5thq.js.map → chevron-left-uSfPn636.js.map} +1 -1
  453. package/dist/web/public/assets/{chevron-right-uP_l9MMb.js → chevron-right-CtelqacW.js} +2 -2
  454. package/dist/web/public/assets/{chevron-right-uP_l9MMb.js.map → chevron-right-CtelqacW.js.map} +1 -1
  455. package/dist/web/public/assets/{circle-check-CewnjFgv.js → circle-check-8dbL-u7O.js} +2 -2
  456. package/dist/web/public/assets/{circle-check-CewnjFgv.js.map → circle-check-8dbL-u7O.js.map} +1 -1
  457. package/dist/web/public/assets/{circle-check-big-C2RTc48c.js → circle-check-big-D8-svk9a.js} +2 -2
  458. package/dist/web/public/assets/{circle-check-big-C2RTc48c.js.map → circle-check-big-D8-svk9a.js.map} +1 -1
  459. package/dist/web/public/assets/{circle-x-Ccg1HyV-.js → circle-x-rUxzIz5P.js} +2 -2
  460. package/dist/web/public/assets/{circle-x-Ccg1HyV-.js.map → circle-x-rUxzIz5P.js.map} +1 -1
  461. package/dist/web/public/assets/{clock-qxbYSynv.js → clock-CG5dlBGB.js} +2 -2
  462. package/dist/web/public/assets/{clock-qxbYSynv.js.map → clock-CG5dlBGB.js.map} +1 -1
  463. package/dist/web/public/assets/{confirm-dialog-DmJq4Td9.js → confirm-dialog-DlUsSur3.js} +2 -2
  464. package/dist/web/public/assets/{confirm-dialog-DmJq4Td9.js.map → confirm-dialog-DlUsSur3.js.map} +1 -1
  465. package/dist/web/public/assets/{copy-DxSHRdbc.js → copy-DnC76wFT.js} +2 -2
  466. package/dist/web/public/assets/{copy-DxSHRdbc.js.map → copy-DnC76wFT.js.map} +1 -1
  467. package/dist/web/public/assets/{data-table-S7rIjwdO.js → data-table-DswkWUfG.js} +2 -2
  468. package/dist/web/public/assets/{data-table-S7rIjwdO.js.map → data-table-DswkWUfG.js.map} +1 -1
  469. package/dist/web/public/assets/dialog-Ceo4YuXy.js +6 -0
  470. package/dist/web/public/assets/dialog-Ceo4YuXy.js.map +1 -0
  471. package/dist/web/public/assets/{download-OhsGtnO-.js → download-DF-46tS4.js} +2 -2
  472. package/dist/web/public/assets/{download-OhsGtnO-.js.map → download-DF-46tS4.js.map} +1 -1
  473. package/dist/web/public/assets/{email-C1-HxWLF.js → email-CZee26-_.js} +3 -3
  474. package/dist/web/public/assets/{email-C1-HxWLF.js.map → email-CZee26-_.js.map} +1 -1
  475. package/dist/web/public/assets/{empty-state-C-qjOHyu.js → empty-state-D9Hi0Atm.js} +2 -2
  476. package/dist/web/public/assets/{empty-state-C-qjOHyu.js.map → empty-state-D9Hi0Atm.js.map} +1 -1
  477. package/dist/web/public/assets/{external-link-DRVp9-lb.js → external-link-D64iZa9P.js} +2 -2
  478. package/dist/web/public/assets/{external-link-DRVp9-lb.js.map → external-link-D64iZa9P.js.map} +1 -1
  479. package/dist/web/public/assets/{eye-CFhg5BTa.js → eye-sY6WZb7D.js} +2 -2
  480. package/dist/web/public/assets/{eye-CFhg5BTa.js.map → eye-sY6WZb7D.js.map} +1 -1
  481. package/dist/web/public/assets/{facts-CGaLWhzi.js → facts-B7bGGwvi.js} +2 -2
  482. package/dist/web/public/assets/{facts-CGaLWhzi.js.map → facts-B7bGGwvi.js.map} +1 -1
  483. package/dist/web/public/assets/{goals-C-dJANmn.js → goals-BfQbsvZv.js} +2 -2
  484. package/dist/web/public/assets/{goals-C-dJANmn.js.map → goals-BfQbsvZv.js.map} +1 -1
  485. package/dist/web/public/assets/{health-CWcti5h3.js → health-Ba_mY0Ts.js} +2 -2
  486. package/dist/web/public/assets/{health-CWcti5h3.js.map → health-Ba_mY0Ts.js.map} +1 -1
  487. package/dist/web/public/assets/{heart-pulse-DmGhKR2W.js → heart-pulse-BjikOVwU.js} +2 -2
  488. package/dist/web/public/assets/{heart-pulse-DmGhKR2W.js.map → heart-pulse-BjikOVwU.js.map} +1 -1
  489. package/dist/web/public/assets/{heartbeat-kLoGBNCo.js → heartbeat-BM8LlPes.js} +2 -2
  490. package/dist/web/public/assets/{heartbeat-kLoGBNCo.js.map → heartbeat-BM8LlPes.js.map} +1 -1
  491. package/dist/web/public/assets/{hot-BITDoax1.js → hot-BtuLL6n8.js} +2 -2
  492. package/dist/web/public/assets/{hot-BITDoax1.js.map → hot-BtuLL6n8.js.map} +1 -1
  493. package/dist/web/public/assets/index-DEWFfW_Z.js +199 -0
  494. package/dist/web/public/assets/index-DEWFfW_Z.js.map +1 -0
  495. package/dist/web/public/assets/{installed-Co9WrtQ7.js → installed-Xr8p31ij.js} +2 -2
  496. package/dist/web/public/assets/{installed-Co9WrtQ7.js.map → installed-Xr8p31ij.js.map} +1 -1
  497. package/dist/web/public/assets/{jobs-hdHhBEvi.js → jobs-Ddy81Udm.js} +2 -2
  498. package/dist/web/public/assets/{jobs-hdHhBEvi.js.map → jobs-Ddy81Udm.js.map} +1 -1
  499. package/dist/web/public/assets/{layout-CQtbOBag.js → layout-BL74fT-L.js} +2 -2
  500. package/dist/web/public/assets/{layout-CQtbOBag.js.map → layout-BL74fT-L.js.map} +1 -1
  501. package/dist/web/public/assets/{layout-bDMXIKIR.js → layout-Bn2qUxcK.js} +2 -2
  502. package/dist/web/public/assets/{layout-bDMXIKIR.js.map → layout-Bn2qUxcK.js.map} +1 -1
  503. package/dist/web/public/assets/{layout-BMXC1Uh1.js → layout-Bp4SAA8_.js} +2 -2
  504. package/dist/web/public/assets/{layout-BMXC1Uh1.js.map → layout-Bp4SAA8_.js.map} +1 -1
  505. package/dist/web/public/assets/{layout-CysVsySh.js → layout-CZ9pGnW8.js} +2 -2
  506. package/dist/web/public/assets/{layout-CysVsySh.js.map → layout-CZ9pGnW8.js.map} +1 -1
  507. package/dist/web/public/assets/{layout-CyBGneZ9.js → layout-pasFRkKV.js} +2 -2
  508. package/dist/web/public/assets/{layout-CyBGneZ9.js.map → layout-pasFRkKV.js.map} +1 -1
  509. package/dist/web/public/assets/llm-yp7b5xxL.js +7 -0
  510. package/dist/web/public/assets/llm-yp7b5xxL.js.map +1 -0
  511. package/dist/web/public/assets/{loader-circle-9VUMGitw.js → loader-circle-Bbw4pEyE.js} +2 -2
  512. package/dist/web/public/assets/{loader-circle-9VUMGitw.js.map → loader-circle-Bbw4pEyE.js.map} +1 -1
  513. package/dist/web/public/assets/{map-pin-BXYvvHry.js → map-pin-DIXHUQgM.js} +2 -2
  514. package/dist/web/public/assets/{map-pin-BXYvvHry.js.map → map-pin-DIXHUQgM.js.map} +1 -1
  515. package/dist/web/public/assets/{mcp-BgLdlwSn.js → mcp-DyaljIM_.js} +2 -2
  516. package/dist/web/public/assets/{mcp-BgLdlwSn.js.map → mcp-DyaljIM_.js.map} +1 -1
  517. package/dist/web/public/assets/memos-Dkoc157i.js +12 -0
  518. package/dist/web/public/assets/memos-Dkoc157i.js.map +1 -0
  519. package/dist/web/public/assets/{messengers-7Phqea62.js → messengers-CcyGDeUI.js} +2 -2
  520. package/dist/web/public/assets/{messengers-7Phqea62.js.map → messengers-CcyGDeUI.js.map} +1 -1
  521. package/dist/web/public/assets/{mobile-CV5b6D2W.js → mobile-DqzIv4Xb.js} +2 -2
  522. package/dist/web/public/assets/{mobile-CV5b6D2W.js.map → mobile-DqzIv4Xb.js.map} +1 -1
  523. package/dist/web/public/assets/{native-agent-QvIa6LjE.js → native-agent-BQ7WaRGK.js} +2 -2
  524. package/dist/web/public/assets/{native-agent-QvIa6LjE.js.map → native-agent-BQ7WaRGK.js.map} +1 -1
  525. package/dist/web/public/assets/{network-BXhEjGhE.js → network-B_yUFAqC.js} +2 -2
  526. package/dist/web/public/assets/{network-BXhEjGhE.js.map → network-B_yUFAqC.js.map} +1 -1
  527. package/dist/web/public/assets/{outbox-DHQL7TQb.js → outbox-l8aVOZqO.js} +2 -2
  528. package/dist/web/public/assets/{outbox-DHQL7TQb.js.map → outbox-l8aVOZqO.js.map} +1 -1
  529. package/dist/web/public/assets/{pagination-VKuPb1Ot.js → pagination-BAKRGKa9.js} +2 -2
  530. package/dist/web/public/assets/{pagination-VKuPb1Ot.js.map → pagination-BAKRGKa9.js.map} +1 -1
  531. package/dist/web/public/assets/{persona-CWug2GLR.js → persona-D3VL9Rg1.js} +2 -2
  532. package/dist/web/public/assets/{persona-CWug2GLR.js.map → persona-D3VL9Rg1.js.map} +1 -1
  533. package/dist/web/public/assets/{plans-CZoEs5SY.js → plans-BBB5e9my.js} +2 -2
  534. package/dist/web/public/assets/{plans-CZoEs5SY.js.map → plans-BBB5e9my.js.map} +1 -1
  535. package/dist/web/public/assets/{play-CfSn5Vdl.js → play-7-Wd369f.js} +2 -2
  536. package/dist/web/public/assets/{play-CfSn5Vdl.js.map → play-7-Wd369f.js.map} +1 -1
  537. package/dist/web/public/assets/{plus-Z8l4CiqJ.js → plus-B0sfZy-j.js} +2 -2
  538. package/dist/web/public/assets/{plus-Z8l4CiqJ.js.map → plus-B0sfZy-j.js.map} +1 -1
  539. package/dist/web/public/assets/{policy-CutDSEPW.js → policy-BM1WRXH0.js} +2 -2
  540. package/dist/web/public/assets/{policy-CutDSEPW.js.map → policy-BM1WRXH0.js.map} +1 -1
  541. package/dist/web/public/assets/{qr-code-DgU5aiM6.js → qr-code-DcKs5fi3.js} +2 -2
  542. package/dist/web/public/assets/{qr-code-DgU5aiM6.js.map → qr-code-DcKs5fi3.js.map} +1 -1
  543. package/dist/web/public/assets/{react-Cb2sDjhD.js → react-DlP5eolq.js} +2 -2
  544. package/dist/web/public/assets/{react-Cb2sDjhD.js.map → react-DlP5eolq.js.map} +1 -1
  545. package/dist/web/public/assets/{refresh-ccw-D2CWiyU_.js → refresh-ccw-uNKeBeRl.js} +2 -2
  546. package/dist/web/public/assets/{refresh-ccw-D2CWiyU_.js.map → refresh-ccw-uNKeBeRl.js.map} +1 -1
  547. package/dist/web/public/assets/{reminders-Cb6Izedg.js → reminders-DHM8K0_O.js} +2 -2
  548. package/dist/web/public/assets/{reminders-Cb6Izedg.js.map → reminders-DHM8K0_O.js.map} +1 -1
  549. package/dist/web/public/assets/{save-DB0BDYTs.js → save-qwJa5_SA.js} +2 -2
  550. package/dist/web/public/assets/{save-DB0BDYTs.js.map → save-qwJa5_SA.js.map} +1 -1
  551. package/dist/web/public/assets/{schedules-8mSjE14D.js → schedules-Bcd0wbT4.js} +2 -2
  552. package/dist/web/public/assets/{schedules-8mSjE14D.js.map → schedules-Bcd0wbT4.js.map} +1 -1
  553. package/dist/web/public/assets/{search-Con69NhG.js → search-BUlzNWrj.js} +2 -2
  554. package/dist/web/public/assets/{search-Con69NhG.js.map → search-BUlzNWrj.js.map} +1 -1
  555. package/dist/web/public/assets/{search-B4fHilZ0.js → search-i1tP2maJ.js} +2 -2
  556. package/dist/web/public/assets/{search-B4fHilZ0.js.map → search-i1tP2maJ.js.map} +1 -1
  557. package/dist/web/public/assets/{security-BTe3zUg8.js → security-DgJyTT4g.js} +2 -2
  558. package/dist/web/public/assets/{security-BTe3zUg8.js.map → security-DgJyTT4g.js.map} +1 -1
  559. package/dist/web/public/assets/{service-C7SqcwfL.js → service-A0Hzear0.js} +2 -2
  560. package/dist/web/public/assets/{service-C7SqcwfL.js.map → service-A0Hzear0.js.map} +1 -1
  561. package/dist/web/public/assets/{shield-alert-CKFVsGgI.js → shield-alert-DrnN6fz_.js} +2 -2
  562. package/dist/web/public/assets/{shield-alert-CKFVsGgI.js.map → shield-alert-DrnN6fz_.js.map} +1 -1
  563. package/dist/web/public/assets/{status-badge-BSkpyN4D.js → status-badge-Ryzf96Pl.js} +2 -2
  564. package/dist/web/public/assets/{status-badge-BSkpyN4D.js.map → status-badge-Ryzf96Pl.js.map} +1 -1
  565. package/dist/web/public/assets/{subtasks-Bel-I1Sk.js → subtasks-Bzh3o3EF.js} +2 -2
  566. package/dist/web/public/assets/{subtasks-Bel-I1Sk.js.map → subtasks-Bzh3o3EF.js.map} +1 -1
  567. package/dist/web/public/assets/{table-CPn1MRcy.js → table-BbAOSyc8.js} +2 -2
  568. package/dist/web/public/assets/{table-CPn1MRcy.js.map → table-BbAOSyc8.js.map} +1 -1
  569. package/dist/web/public/assets/{topn-Ba3RjcK1.js → topn-DkhYw-Gp.js} +2 -2
  570. package/dist/web/public/assets/{topn-Ba3RjcK1.js.map → topn-DkhYw-Gp.js.map} +1 -1
  571. package/dist/web/public/assets/{trash-2-Dfov8aHD.js → trash-2-CA0cLpnU.js} +2 -2
  572. package/dist/web/public/assets/{trash-2-Dfov8aHD.js.map → trash-2-CA0cLpnU.js.map} +1 -1
  573. package/dist/web/public/assets/{use-background-tasks-BQrEeUwY.js → use-background-tasks-B64YjlA8.js} +2 -2
  574. package/dist/web/public/assets/{use-background-tasks-BQrEeUwY.js.map → use-background-tasks-B64YjlA8.js.map} +1 -1
  575. package/dist/web/public/assets/{use-event-stream-DgGpGKop.js → use-event-stream-I1lMFEfh.js} +2 -2
  576. package/dist/web/public/assets/{use-event-stream-DgGpGKop.js.map → use-event-stream-I1lMFEfh.js.map} +1 -1
  577. package/dist/web/public/assets/{use-llm-admin-DYekqogG.js → use-llm-admin-DY2axI4D.js} +2 -2
  578. package/dist/web/public/assets/{use-llm-admin-DYekqogG.js.map → use-llm-admin-DY2axI4D.js.map} +1 -1
  579. package/dist/web/public/assets/{use-memory-DbJ4pP2Z.js → use-memory-BYEjVWbU.js} +2 -2
  580. package/dist/web/public/assets/{use-memory-DbJ4pP2Z.js.map → use-memory-BYEjVWbU.js.map} +1 -1
  581. package/dist/web/public/assets/{use-observability-C2M6WZ9W.js → use-observability-Coj02yDo.js} +2 -2
  582. package/dist/web/public/assets/{use-observability-C2M6WZ9W.js.map → use-observability-Coj02yDo.js.map} +1 -1
  583. package/dist/web/public/assets/{use-settings-DMdaoWsB.js → use-settings-i1MhlkyC.js} +2 -2
  584. package/dist/web/public/assets/{use-settings-DMdaoWsB.js.map → use-settings-i1MhlkyC.js.map} +1 -1
  585. package/dist/web/public/assets/{use-workspace-BHG7h3jQ.js → use-workspace-DgEM35PY.js} +2 -2
  586. package/dist/web/public/assets/{use-workspace-BHG7h3jQ.js.map → use-workspace-DgEM35PY.js.map} +1 -1
  587. package/dist/web/public/assets/{useQuery-PdiC7-sY.js → useQuery-CY2iazjN.js} +2 -2
  588. package/dist/web/public/assets/{useQuery-PdiC7-sY.js.map → useQuery-CY2iazjN.js.map} +1 -1
  589. package/dist/web/public/assets/{vector-DnZM3OXU.js → vector-Ic76u2hY.js} +2 -2
  590. package/dist/web/public/assets/{vector-DnZM3OXU.js.map → vector-Ic76u2hY.js.map} +1 -1
  591. package/dist/web/public/assets/{viewer-Dz6k0YKp.js → viewer-BXbUN1Rl.js} +2 -2
  592. package/dist/web/public/assets/{viewer-Dz6k0YKp.js.map → viewer-BXbUN1Rl.js.map} +1 -1
  593. package/dist/web/public/assets/{workspace-BnXrWS3j.js → workspace-CUg0JPn6.js} +3 -3
  594. package/dist/web/public/assets/{workspace-BnXrWS3j.js.map → workspace-CUg0JPn6.js.map} +1 -1
  595. package/dist/web/public/assets/{workspaces-CSS_UBEi.js → workspaces-C-wb5FQj.js} +2 -2
  596. package/dist/web/public/assets/{workspaces-CSS_UBEi.js.map → workspaces-C-wb5FQj.js.map} +1 -1
  597. package/dist/web/public/assets/{x-DG-JKVw_.js → x-D1iSuoqg.js} +2 -2
  598. package/dist/web/public/assets/{x-DG-JKVw_.js.map → x-D1iSuoqg.js.map} +1 -1
  599. package/dist/web/public/index.html +2 -2
  600. package/dist/web/server.d.ts.map +1 -1
  601. package/dist/web/server.js +6 -0
  602. package/dist/web/server.js.map +1 -1
  603. package/package.json +1 -1
  604. package/dist/web/public/assets/dialog-bAIDaO-6.js +0 -6
  605. package/dist/web/public/assets/dialog-bAIDaO-6.js.map +0 -1
  606. package/dist/web/public/assets/index-O0BQoyzo.js +0 -199
  607. package/dist/web/public/assets/index-O0BQoyzo.js.map +0 -1
  608. package/dist/web/public/assets/llm-CPIRNQU2.js +0 -7
  609. package/dist/web/public/assets/llm-CPIRNQU2.js.map +0 -1
  610. package/dist/web/public/assets/memos-CfneX9DH.js +0 -12
  611. package/dist/web/public/assets/memos-CfneX9DH.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"security-BTe3zUg8.js","sources":["../../src/routes/settings/security.tsx"],"sourcesContent":["/**\n * /settings/security — central console for v1.2.66 security controls.\n *\n * Lays out:\n * • Diagnostics card (read-only) — uid 0? env file perms? bwrap? allowlists configured?\n * • Sender allowlist (IMHUB_ALLOWED_USERS)\n * • Native exec (IMHUB_EXEC_SANDBOX, IMHUB_EXEC_SANDBOX_NET, IMHUB_EXEC_TIMEOUT_MS, IMHUB_EXEC_MAX_OUTPUT)\n * • Native web (IMHUB_NATIVE_WEB_ALLOW_PRIVATE, IMHUB_NATIVE_WEB_SSRF_WHITELIST, IMHUB_NATIVE_WEB_TIMEOUT_MS)\n * • Native fs (IMHUB_NATIVE_FS_RESTRICT, IMHUB_NATIVE_FS_TIMEOUT_MS)\n * • Delegation (IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN)\n *\n * All writes go through PUT /api/env (admin-gated). Most knobs are\n * hot-reloaded (read process.env per tool call); the exec sandbox +\n * sender allowlist apply at boot — service restart required.\n */\n\nimport { useEffect, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { AlertTriangle, CheckCircle2, Loader2, RefreshCcw, ShieldAlert } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv } from '@/hooks/use-settings'\nimport { client } from '@/lib/api/client'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\ninterface Diagnostics {\n runningAsRoot: boolean | null\n envFile: { exists: boolean; mode: string | null; tooPermissive: boolean }\n bwrapAvailable: boolean\n senderAllowlistConfigured: boolean\n adminAllowlistConfigured: boolean\n platformBlacklist: string[]\n liveEnv: Record<string, string | null>\n}\n\nfunction envBool(v: string | undefined): boolean {\n if (v == null) return false\n const t = v.toLowerCase()\n return t === '1' || t === 'true' || t === 'yes' || t === 'on'\n}\n\nexport default function SettingsSecurityRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv()\n const updateEnv = useUpdateEnv()\n const [diagnostics, setDiagnostics] = useState<Diagnostics | null>(null)\n const [diagLoading, setDiagLoading] = useState(false)\n\n async function loadDiagnostics(): Promise<void> {\n setDiagLoading(true)\n try {\n const res = await client.get<{ diagnostics: Diagnostics }>('/api/security/diagnostics')\n setDiagnostics(res.diagnostics)\n } catch (err) {\n toast.error(describeError(err, t).message)\n } finally {\n setDiagLoading(false)\n }\n }\n\n useEffect(() => { void loadDiagnostics() }, [])\n\n async function setValue(key: string, value: string | null): Promise<void> {\n try {\n await updateEnv.mutateAsync({ updates: { [key]: value } })\n toast.success(t('security.savingToast'))\n await loadDiagnostics()\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const env = envQuery.data?.env ?? {}\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('security.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => { void envQuery.refetch(); void loadDiagnostics() }}\n disabled={envQuery.isFetching || diagLoading}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || diagLoading\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />\n }\n </Button>\n </div>\n <p className=\"text-sm text-muted\">{t('security.subtitle')}</p>\n </header>\n\n {/* Diagnostics card */}\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold\">\n <ShieldAlert className=\"h-4 w-4\" />\n {t('security.diagnostics.title')}\n </h2>\n {diagnostics ? (\n <ul className=\"grid gap-2 text-sm sm:grid-cols-2\">\n <DiagRow\n label={t('security.diagnostics.runningAsRoot')}\n ok={diagnostics.runningAsRoot === false}\n text={diagnostics.runningAsRoot === true ? t('security.diagnostics.runningAsRootHelp') : 'OK'}\n />\n <DiagRow\n label={t('security.diagnostics.envFilePerms')}\n ok={diagnostics.envFile.exists && !diagnostics.envFile.tooPermissive}\n text={\n !diagnostics.envFile.exists\n ? '—'\n : diagnostics.envFile.tooPermissive\n ? `${diagnostics.envFile.mode} — ${t('security.diagnostics.envFilePermsLax')}`\n : t('security.diagnostics.envFilePermsOk')\n }\n />\n <DiagRow\n label={t('security.diagnostics.bwrapAvailable')}\n ok={diagnostics.bwrapAvailable}\n text={diagnostics.bwrapAvailable ? '/usr/bin/bwrap' : t('security.diagnostics.bwrapMissing')}\n />\n <DiagRow\n label={t('security.diagnostics.senderAllowlist')}\n ok={diagnostics.senderAllowlistConfigured}\n text={diagnostics.senderAllowlistConfigured\n ? t('security.diagnostics.senderAllowlistOn')\n : t('security.diagnostics.senderAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnostics.adminAllowlist')}\n ok={diagnostics.adminAllowlistConfigured}\n text={diagnostics.adminAllowlistConfigured\n ? t('security.diagnostics.adminAllowlistOn')\n : t('security.diagnostics.adminAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnosticsPlatformBlacklist')}\n ok={diagnostics.platformBlacklist.length === 0}\n text={diagnostics.platformBlacklist.length === 0\n ? '—'\n : diagnostics.platformBlacklist.join(', ')\n }\n />\n </ul>\n ) : (\n <p className=\"text-sm text-muted\">…</p>\n )}\n </section>\n\n {/* Sender allowlist */}\n <ControlCard\n title={t('security.sender.title')}\n description={t('security.sender.description')}\n envKey=\"IMHUB_ALLOWED_USERS\"\n >\n <Input\n defaultValue={env.IMHUB_ALLOWED_USERS ?? ''}\n placeholder={t('security.sender.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_ALLOWED_USERS', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* Exec sandbox */}\n <ControlCard\n title={t('security.exec.title')}\n description={t('security.exec.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.exec.sandbox')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX ?? '').toLowerCase() === 'bwrap' ? 'bwrap' : '__none__'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX', v === '__none__' ? null : v)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none__\">{t('security.exec.sandboxNone')}</SelectItem>\n <SelectItem\n value=\"bwrap\"\n disabled={!diagnostics?.bwrapAvailable}\n >\n {t('security.exec.sandboxBwrap')}\n {!diagnostics?.bwrapAvailable && (\n <span className=\"ml-2 text-xs text-muted\">\n ({t('security.exec.sandboxBwrapMissing')})\n </span>\n )}\n </SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.sandboxNet')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX_NET ?? '').toLowerCase() === 'off' ? 'off' : 'on'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX_NET', v === 'off' ? 'off' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"on\">{t('security.exec.sandboxNetOn')}</SelectItem>\n <SelectItem value=\"off\">{t('security.exec.sandboxNetOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <LabeledField label={t('security.exec.maxOutput')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_MAX_OUTPUT ?? ''}\n placeholder=\"32768\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_MAX_OUTPUT', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Web SSRF */}\n <ControlCard\n title={t('security.web.title')}\n description={t('security.web.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.web.allowPrivate')} hint={t('security.web.allowPrivateHelp')}>\n <Select\n value={envBool(env.IMHUB_NATIVE_WEB_ALLOW_PRIVATE) ? '1' : '0'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_WEB_ALLOW_PRIVATE', v === '1' ? '1' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"0\">OFF</SelectItem>\n <SelectItem value=\"1\">ON</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.web.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_WEB_TIMEOUT_MS ?? ''}\n placeholder=\"30000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <div className=\"sm:col-span-2\">\n <LabeledField label={t('security.web.ssrfWhitelist')}>\n <Input\n defaultValue={env.IMHUB_NATIVE_WEB_SSRF_WHITELIST ?? ''}\n placeholder={t('security.web.ssrfWhitelistPlaceholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_SSRF_WHITELIST', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </div>\n </ControlCard>\n\n {/* FS */}\n <ControlCard\n title={t('security.fs.title')}\n description={t('security.fs.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.fs.restrict')}>\n <Select\n value={(env.IMHUB_NATIVE_FS_RESTRICT ?? '1') === '0' ? '0' : '1'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_FS_RESTRICT', v === '0' ? '0' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"1\">{t('security.fs.restrictOn')}</SelectItem>\n <SelectItem value=\"0\">{t('security.fs.restrictOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.fs.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_FS_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_FS_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Delegation cap */}\n <ControlCard\n title={t('security.delegation.title')}\n description={t('security.delegation.description')}\n envKey=\"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN\"\n >\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN ?? ''}\n placeholder=\"2\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* IM platform blacklist */}\n <ControlCard\n title={t('security.platformBlacklist.title')}\n description={t('security.platformBlacklist.description')}\n envKey=\"IMHUB_PLATFORM_BLACKLIST\"\n >\n <Input\n defaultValue={env.IMHUB_PLATFORM_BLACKLIST ?? ''}\n placeholder={t('security.platformBlacklist.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_PLATFORM_BLACKLIST', v === '' ? null : v)\n }}\n />\n {diagnostics?.platformBlacklist && diagnostics.platformBlacklist.length > 0 && (\n <p className=\"mt-2 text-[10px] text-muted\">\n {t('security.platformBlacklist.currentLabel')}: {diagnostics.platformBlacklist.join(', ')}\n </p>\n )}\n </ControlCard>\n </div>\n )\n}\n\nfunction DiagRow({ label, ok, text }: { label: string; ok: boolean; text: string }): JSX.Element {\n return (\n <li className=\"flex items-start gap-2\">\n {ok\n ? <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-success\" />\n : <AlertTriangle className=\"mt-0.5 h-4 w-4 shrink-0 text-warning\" />\n }\n <div className=\"flex-1\">\n <div className=\"font-medium\">{label}</div>\n <div className={cn('text-xs', ok ? 'text-muted' : 'text-warning')}>{text}</div>\n </div>\n </li>\n )\n}\n\nfunction ControlCard({\n title, description, envKey, children,\n}: { title: string; description: string; envKey?: string; children: React.ReactNode }): JSX.Element {\n return (\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <div className=\"mb-2 flex flex-wrap items-baseline gap-2\">\n <h2 className=\"text-sm font-semibold\">{title}</h2>\n {envKey && <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{envKey}</Badge>}\n </div>\n <p className=\"mb-3 text-xs text-muted\">{description}</p>\n {children}\n </section>\n )\n}\n\nfunction LabeledField({\n label, hint, children,\n}: { label: string; hint?: string; children: React.ReactNode }): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <label className=\"text-xs font-medium text-muted\">{label}</label>\n {children}\n {hint && <p className=\"text-[10px] text-muted\">{hint}</p>}\n </div>\n )\n}\n"],"names":["envBool","v","t","SettingsSecurityRoute","useTranslation","envQuery","useEnv","updateEnv","useUpdateEnv","diagnostics","setDiagnostics","useState","diagLoading","setDiagLoading","loadDiagnostics","res","client","err","toast","describeError","useEffect","setValue","key","value","env","jsxs","jsx","Button","Loader2","RefreshCcw","ShieldAlert","DiagRow","ControlCard","Input","e","LabeledField","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","label","ok","text","CheckCircle2","AlertTriangle","cn","title","description","envKey","children","Badge","hint"],"mappings":"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"}
1
+ {"version":3,"file":"security-DgJyTT4g.js","sources":["../../src/routes/settings/security.tsx"],"sourcesContent":["/**\n * /settings/security — central console for v1.2.66 security controls.\n *\n * Lays out:\n * • Diagnostics card (read-only) — uid 0? env file perms? bwrap? allowlists configured?\n * • Sender allowlist (IMHUB_ALLOWED_USERS)\n * • Native exec (IMHUB_EXEC_SANDBOX, IMHUB_EXEC_SANDBOX_NET, IMHUB_EXEC_TIMEOUT_MS, IMHUB_EXEC_MAX_OUTPUT)\n * • Native web (IMHUB_NATIVE_WEB_ALLOW_PRIVATE, IMHUB_NATIVE_WEB_SSRF_WHITELIST, IMHUB_NATIVE_WEB_TIMEOUT_MS)\n * • Native fs (IMHUB_NATIVE_FS_RESTRICT, IMHUB_NATIVE_FS_TIMEOUT_MS)\n * • Delegation (IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN)\n *\n * All writes go through PUT /api/env (admin-gated). Most knobs are\n * hot-reloaded (read process.env per tool call); the exec sandbox +\n * sender allowlist apply at boot — service restart required.\n */\n\nimport { useEffect, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { AlertTriangle, CheckCircle2, Loader2, RefreshCcw, ShieldAlert } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv } from '@/hooks/use-settings'\nimport { client } from '@/lib/api/client'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\ninterface Diagnostics {\n runningAsRoot: boolean | null\n envFile: { exists: boolean; mode: string | null; tooPermissive: boolean }\n bwrapAvailable: boolean\n senderAllowlistConfigured: boolean\n adminAllowlistConfigured: boolean\n platformBlacklist: string[]\n liveEnv: Record<string, string | null>\n}\n\nfunction envBool(v: string | undefined): boolean {\n if (v == null) return false\n const t = v.toLowerCase()\n return t === '1' || t === 'true' || t === 'yes' || t === 'on'\n}\n\nexport default function SettingsSecurityRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv()\n const updateEnv = useUpdateEnv()\n const [diagnostics, setDiagnostics] = useState<Diagnostics | null>(null)\n const [diagLoading, setDiagLoading] = useState(false)\n\n async function loadDiagnostics(): Promise<void> {\n setDiagLoading(true)\n try {\n const res = await client.get<{ diagnostics: Diagnostics }>('/api/security/diagnostics')\n setDiagnostics(res.diagnostics)\n } catch (err) {\n toast.error(describeError(err, t).message)\n } finally {\n setDiagLoading(false)\n }\n }\n\n useEffect(() => { void loadDiagnostics() }, [])\n\n async function setValue(key: string, value: string | null): Promise<void> {\n try {\n await updateEnv.mutateAsync({ updates: { [key]: value } })\n toast.success(t('security.savingToast'))\n await loadDiagnostics()\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const env = envQuery.data?.env ?? {}\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('security.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => { void envQuery.refetch(); void loadDiagnostics() }}\n disabled={envQuery.isFetching || diagLoading}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || diagLoading\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />\n }\n </Button>\n </div>\n <p className=\"text-sm text-muted\">{t('security.subtitle')}</p>\n </header>\n\n {/* Diagnostics card */}\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold\">\n <ShieldAlert className=\"h-4 w-4\" />\n {t('security.diagnostics.title')}\n </h2>\n {diagnostics ? (\n <ul className=\"grid gap-2 text-sm sm:grid-cols-2\">\n <DiagRow\n label={t('security.diagnostics.runningAsRoot')}\n ok={diagnostics.runningAsRoot === false}\n text={diagnostics.runningAsRoot === true ? t('security.diagnostics.runningAsRootHelp') : 'OK'}\n />\n <DiagRow\n label={t('security.diagnostics.envFilePerms')}\n ok={diagnostics.envFile.exists && !diagnostics.envFile.tooPermissive}\n text={\n !diagnostics.envFile.exists\n ? '—'\n : diagnostics.envFile.tooPermissive\n ? `${diagnostics.envFile.mode} — ${t('security.diagnostics.envFilePermsLax')}`\n : t('security.diagnostics.envFilePermsOk')\n }\n />\n <DiagRow\n label={t('security.diagnostics.bwrapAvailable')}\n ok={diagnostics.bwrapAvailable}\n text={diagnostics.bwrapAvailable ? '/usr/bin/bwrap' : t('security.diagnostics.bwrapMissing')}\n />\n <DiagRow\n label={t('security.diagnostics.senderAllowlist')}\n ok={diagnostics.senderAllowlistConfigured}\n text={diagnostics.senderAllowlistConfigured\n ? t('security.diagnostics.senderAllowlistOn')\n : t('security.diagnostics.senderAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnostics.adminAllowlist')}\n ok={diagnostics.adminAllowlistConfigured}\n text={diagnostics.adminAllowlistConfigured\n ? t('security.diagnostics.adminAllowlistOn')\n : t('security.diagnostics.adminAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnosticsPlatformBlacklist')}\n ok={diagnostics.platformBlacklist.length === 0}\n text={diagnostics.platformBlacklist.length === 0\n ? '—'\n : diagnostics.platformBlacklist.join(', ')\n }\n />\n </ul>\n ) : (\n <p className=\"text-sm text-muted\">…</p>\n )}\n </section>\n\n {/* Sender allowlist */}\n <ControlCard\n title={t('security.sender.title')}\n description={t('security.sender.description')}\n envKey=\"IMHUB_ALLOWED_USERS\"\n >\n <Input\n defaultValue={env.IMHUB_ALLOWED_USERS ?? ''}\n placeholder={t('security.sender.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_ALLOWED_USERS', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* Exec sandbox */}\n <ControlCard\n title={t('security.exec.title')}\n description={t('security.exec.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.exec.sandbox')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX ?? '').toLowerCase() === 'bwrap' ? 'bwrap' : '__none__'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX', v === '__none__' ? null : v)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none__\">{t('security.exec.sandboxNone')}</SelectItem>\n <SelectItem\n value=\"bwrap\"\n disabled={!diagnostics?.bwrapAvailable}\n >\n {t('security.exec.sandboxBwrap')}\n {!diagnostics?.bwrapAvailable && (\n <span className=\"ml-2 text-xs text-muted\">\n ({t('security.exec.sandboxBwrapMissing')})\n </span>\n )}\n </SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.sandboxNet')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX_NET ?? '').toLowerCase() === 'off' ? 'off' : 'on'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX_NET', v === 'off' ? 'off' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"on\">{t('security.exec.sandboxNetOn')}</SelectItem>\n <SelectItem value=\"off\">{t('security.exec.sandboxNetOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <LabeledField label={t('security.exec.maxOutput')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_MAX_OUTPUT ?? ''}\n placeholder=\"32768\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_MAX_OUTPUT', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Web SSRF */}\n <ControlCard\n title={t('security.web.title')}\n description={t('security.web.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.web.allowPrivate')} hint={t('security.web.allowPrivateHelp')}>\n <Select\n value={envBool(env.IMHUB_NATIVE_WEB_ALLOW_PRIVATE) ? '1' : '0'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_WEB_ALLOW_PRIVATE', v === '1' ? '1' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"0\">OFF</SelectItem>\n <SelectItem value=\"1\">ON</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.web.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_WEB_TIMEOUT_MS ?? ''}\n placeholder=\"30000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <div className=\"sm:col-span-2\">\n <LabeledField label={t('security.web.ssrfWhitelist')}>\n <Input\n defaultValue={env.IMHUB_NATIVE_WEB_SSRF_WHITELIST ?? ''}\n placeholder={t('security.web.ssrfWhitelistPlaceholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_SSRF_WHITELIST', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </div>\n </ControlCard>\n\n {/* FS */}\n <ControlCard\n title={t('security.fs.title')}\n description={t('security.fs.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.fs.restrict')}>\n <Select\n value={(env.IMHUB_NATIVE_FS_RESTRICT ?? '1') === '0' ? '0' : '1'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_FS_RESTRICT', v === '0' ? '0' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"1\">{t('security.fs.restrictOn')}</SelectItem>\n <SelectItem value=\"0\">{t('security.fs.restrictOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.fs.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_FS_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_FS_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Delegation cap */}\n <ControlCard\n title={t('security.delegation.title')}\n description={t('security.delegation.description')}\n envKey=\"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN\"\n >\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN ?? ''}\n placeholder=\"2\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* IM platform blacklist */}\n <ControlCard\n title={t('security.platformBlacklist.title')}\n description={t('security.platformBlacklist.description')}\n envKey=\"IMHUB_PLATFORM_BLACKLIST\"\n >\n <Input\n defaultValue={env.IMHUB_PLATFORM_BLACKLIST ?? ''}\n placeholder={t('security.platformBlacklist.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_PLATFORM_BLACKLIST', v === '' ? null : v)\n }}\n />\n {diagnostics?.platformBlacklist && diagnostics.platformBlacklist.length > 0 && (\n <p className=\"mt-2 text-[10px] text-muted\">\n {t('security.platformBlacklist.currentLabel')}: {diagnostics.platformBlacklist.join(', ')}\n </p>\n )}\n </ControlCard>\n </div>\n )\n}\n\nfunction DiagRow({ label, ok, text }: { label: string; ok: boolean; text: string }): JSX.Element {\n return (\n <li className=\"flex items-start gap-2\">\n {ok\n ? <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-success\" />\n : <AlertTriangle className=\"mt-0.5 h-4 w-4 shrink-0 text-warning\" />\n }\n <div className=\"flex-1\">\n <div className=\"font-medium\">{label}</div>\n <div className={cn('text-xs', ok ? 'text-muted' : 'text-warning')}>{text}</div>\n </div>\n </li>\n )\n}\n\nfunction ControlCard({\n title, description, envKey, children,\n}: { title: string; description: string; envKey?: string; children: React.ReactNode }): JSX.Element {\n return (\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <div className=\"mb-2 flex flex-wrap items-baseline gap-2\">\n <h2 className=\"text-sm font-semibold\">{title}</h2>\n {envKey && <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{envKey}</Badge>}\n </div>\n <p className=\"mb-3 text-xs text-muted\">{description}</p>\n {children}\n </section>\n )\n}\n\nfunction LabeledField({\n label, hint, children,\n}: { label: string; hint?: string; children: React.ReactNode }): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <label className=\"text-xs font-medium text-muted\">{label}</label>\n {children}\n {hint && <p className=\"text-[10px] text-muted\">{hint}</p>}\n </div>\n )\n}\n"],"names":["envBool","v","t","SettingsSecurityRoute","useTranslation","envQuery","useEnv","updateEnv","useUpdateEnv","diagnostics","setDiagnostics","useState","diagLoading","setDiagLoading","loadDiagnostics","res","client","err","toast","describeError","useEffect","setValue","key","value","env","jsxs","jsx","Button","Loader2","RefreshCcw","ShieldAlert","DiagRow","ControlCard","Input","e","LabeledField","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","label","ok","text","CheckCircle2","AlertTriangle","cn","title","description","envKey","children","Badge","hint"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import{n as z,u as P,j as e,B as f,k as L,R as T,c as w,l as m,m as v,L as U,I as _}from"./index-O0BQoyzo.js";import{r as p}from"./react-Cb2sDjhD.js";import{C as y}from"./confirm-dialog-DmJq4Td9.js";import{j as O,k as B,l as W,m as q,b as M,c as H}from"./use-settings-DMdaoWsB.js";import{L as S}from"./loader-circle-9VUMGitw.js";import{R as Q}from"./refresh-ccw-D2CWiyU_.js";import{P as V}from"./play-CfSn5Vdl.js";import{N as X}from"./network-BXhEjGhE.js";import{X as $}from"./x-DG-JKVw_.js";import{S as G}from"./save-DB0BDYTs.js";import"./dialog-bAIDaO-6.js";import"./useQuery-PdiC7-sY.js";/**
1
+ import{n as z,u as P,j as e,B as f,k as L,R as T,c as w,l as m,m as v,L as U,I as _}from"./index-DEWFfW_Z.js";import{r as p}from"./react-DlP5eolq.js";import{C as y}from"./confirm-dialog-DlUsSur3.js";import{j as O,k as B,l as W,m as q,b as M,c as H}from"./use-settings-i1MhlkyC.js";import{L as S}from"./loader-circle-Bbw4pEyE.js";import{R as Q}from"./refresh-ccw-uNKeBeRl.js";import{P as V}from"./play-7-Wd369f.js";import{N as X}from"./network-B_yUFAqC.js";import{X as $}from"./x-D1iSuoqg.js";import{S as G}from"./save-qwJa5_SA.js";import"./dialog-Ceo4YuXy.js";import"./useQuery-CY2iazjN.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const J=z("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]),K={systemd:"success",background:"info",foreground:"warning",none:"default"},C=3e3,k=9090;function me(){const{t:s}=P(["settings","common"]),r=O(),t=r.data,a=t&&t.mode!=="none",i=B(),n=W(),o=q(),[u,x]=p.useState(!1),[h,g]=p.useState(!1);async function b(){try{await i.mutateAsync(),m.success(s("service.toast.started"))}catch(c){m.error(v(c,s).message)}}async function d(){try{await n.mutateAsync(),m.success(s("service.toast.stopped"))}catch(c){throw m.error(v(c,s).message),c}}async function l(){try{await o.mutateAsync(),m.success(s("service.toast.restarted"))}catch(c){throw m.error(v(c,s).message),c}}return e.jsxs("div",{className:"mx-auto flex max-w-3xl flex-col gap-4",children:[e.jsxs("header",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("service.title")}),e.jsxs(f,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>r.refetch(),disabled:r.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[r.isFetching?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(Q,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("actions.refresh",{ns:"common"})})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:s("service.subtitle")})]}),e.jsx(Y,{}),r.isLoading?e.jsx("div",{className:"h-48 rounded-md bg-surface-2 animate-pulse"}):t?e.jsxs("div",{className:"rounded-md border border-border bg-surface p-4",children:[e.jsxs("dl",{className:"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 text-sm",children:[e.jsx("dt",{className:"text-text-dim",children:s("service.modeLabel")}),e.jsx("dd",{children:e.jsx(L,{variant:K[t.mode],children:s(`service.mode.${t.mode}`)})}),t.pid!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-text-dim",children:s("service.pidLabel")}),e.jsx("dd",{className:"tabular-nums font-mono",children:t.pid})]}),t.uptime&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-text-dim",children:s("service.uptimeLabel")}),e.jsx("dd",{className:"tabular-nums",children:t.uptime})]}),t.web&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-text-dim",children:s("service.webLabel")}),e.jsxs("dd",{className:"font-mono text-xs",children:[t.web.bind,":",t.web.port]})]}),e.jsx("dt",{className:"text-text-dim",children:s("service.bootPhaseLabel")}),e.jsx("dd",{children:e.jsx("code",{className:"rounded bg-surface-2 px-1.5 py-0.5 text-xs",children:t.bootPhase})})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsxs(f,{type:"button",variant:"default",size:"sm",disabled:a||i.isPending,onClick:()=>void b(),children:[i.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(V,{className:"h-4 w-4"}),s("service.actions.start")]}),e.jsxs(f,{type:"button",variant:"outline",size:"sm",disabled:!a||o.isPending,onClick:()=>g(!0),children:[e.jsx(T,{className:w("h-4 w-4",o.isPending&&"animate-spin")}),s("service.actions.restart")]}),e.jsxs(f,{type:"button",variant:"destructive",size:"sm",disabled:!a||n.isPending,onClick:()=>x(!0),children:[e.jsx(J,{className:"h-4 w-4"}),s("service.actions.stop")]})]})]}):null,e.jsx(y,{open:u,onOpenChange:x,title:s("service.actions.confirmStop"),description:s("service.actions.confirmStopDesc"),intent:"danger",confirmLabel:s("service.actions.stop"),onConfirm:d}),e.jsx(y,{open:h,onOpenChange:g,title:s("service.actions.confirmRestart"),description:s("service.actions.confirmRestartDesc"),intent:"danger",confirmLabel:s("service.actions.restart"),onConfirm:l})]})}function A(s){const r=s.trim();if(!r)return{ok:!0,value:void 0};const t=Number.parseInt(r,10);return!Number.isFinite(t)||t<1||t>65535?{ok:!1}:{ok:!0,value:t}}function Y(){const{t:s}=P(["settings","common"]),r=M(),t=H(),a=r.data,i=a?.webPort,n=a?.acpPort,[o,u]=p.useState(""),[x,h]=p.useState(""),[g,b]=p.useState(0);p.useEffect(()=>{a&&r.dataUpdatedAt!==g&&(u(i!=null?String(i):""),h(n!=null?String(n):""),b(r.dataUpdatedAt))},[a,r.dataUpdatedAt,i,n,g]);const d=A(o),l=A(x),c=!d.ok,j=!l.ok,D=p.useMemo(()=>{if(!a)return!1;const N=d.ok?d.value:void 0,I=l.ok?l.value:void 0;return N!==i||I!==n},[a,d,l,i,n]);function F(){u(i!=null?String(i):""),h(n!=null?String(n):"")}async function E(){if(!(!a||c||j))try{await t.mutateAsync({...a,webPort:d.ok?d.value:void 0,acpPort:l.ok?l.value:void 0}),m.success(s("service.ports.toast.saved"))}catch(N){m.error(v(N,s).message)}}return r.isLoading?e.jsx("div",{className:"h-32 rounded-md bg-surface-2 animate-pulse"}):e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(X,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("service.ports.title")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:s("service.ports.subtitle")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 px-4 py-3 sm:grid-cols-2",children:[e.jsx(R,{id:"web-port",label:s("service.ports.webPort"),hint:s("service.ports.webPortHint",{default:C}),value:o,onChange:u,invalid:c,placeholder:String(C)}),a?.features?.remoteAgent?e.jsx(R,{id:"acp-port",label:s("service.ports.acpPort"),hint:s("service.ports.acpPortHint",{default:k}),value:x,onChange:h,invalid:j,placeholder:String(k)}):null]}),D&&e.jsxs("div",{className:"flex items-center gap-2 border-t border-border px-4 py-3",children:[e.jsx(L,{variant:"warning",children:s("service.ports.restartRequired")}),e.jsxs(f,{variant:"ghost",size:"sm",className:"ml-auto",onClick:F,disabled:t.isPending,children:[e.jsx($,{className:"h-4 w-4"}),s("service.ports.discard")]}),e.jsxs(f,{size:"sm",onClick:()=>void E(),disabled:t.isPending||c||j,children:[t.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(G,{className:"h-4 w-4"}),t.isPending?s("service.ports.saving"):s("service.ports.save")]})]})]})}function R({id:s,label:r,hint:t,value:a,onChange:i,invalid:n,placeholder:o}){const{t:u}=P("settings");return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(U,{htmlFor:s,className:"text-xs font-medium",children:r}),e.jsx(_,{id:s,type:"number",inputMode:"numeric",min:1,max:65535,value:a,onChange:x=>i(x.target.value),placeholder:o,"aria-invalid":n,className:w("font-mono",n&&"border-danger focus:ring-danger")}),e.jsx("p",{className:w("text-[11px]",n?"text-danger":"text-text-dim"),children:n?u("service.ports.invalidPort"):t})]})}export{me as default};
7
- //# sourceMappingURL=service-C7SqcwfL.js.map
7
+ //# sourceMappingURL=service-A0Hzear0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-C7SqcwfL.js","sources":["../../node_modules/lucide-react/dist/esm/icons/square.js","../../src/routes/settings/service.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Square = createLucideIcon(\"Square\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n]);\n\nexport { Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * /settings/service — operator-facing process control: see the\n * running agim daemon's mode/pid/uptime + start, stop, or restart it.\n *\n * R8 (this round) added a dedicated \"Ports\" card at the top covering\n * webPort + acpPort. They live in `~/.agim/config.json` (PUT /api/config),\n * and take effect on the next service restart — handled by the\n * Start/Restart buttons immediately below.\n *\n * Stop and restart go through ConfirmDialog because they\n * permanently interrupt every messenger adapter + in-flight job;\n * Start is one-click since it's safe to invoke even when already\n * running (backend short-circuits to alreadyRunning:true).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n Loader2, Network, Play, RefreshCcw, RotateCcw, Save, Square, X,\n} from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n useConfig,\n useRestartService,\n useServiceStatus,\n useStartService,\n useStopService,\n useUpdateConfig,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { ServiceMode } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst MODE_VARIANT: Record<ServiceMode, 'success' | 'info' | 'warning' | 'default'> = {\n systemd: 'success',\n background: 'info',\n foreground: 'warning',\n none: 'default',\n}\n\nconst DEFAULT_WEB_PORT = 3000\nconst DEFAULT_ACP_PORT = 9090\n\nexport default function SettingsServiceRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const status = useServiceStatus()\n const data = status.data\n const isRunning = data && data.mode !== 'none'\n\n const start = useStartService()\n const stop = useStopService()\n const restart = useRestartService()\n\n const [confirmStop, setConfirmStop] = useState(false)\n const [confirmRestart, setConfirmRestart] = useState(false)\n\n async function onStart(): Promise<void> {\n try {\n await start.mutateAsync()\n toast.success(t('service.toast.started'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n async function onConfirmStop(): Promise<void> {\n try {\n await stop.mutateAsync()\n toast.success(t('service.toast.stopped'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n async function onConfirmRestart(): Promise<void> {\n try {\n await restart.mutateAsync()\n toast.success(t('service.toast.restarted'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-3xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('service.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => status.refetch()}\n disabled={status.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {status.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('service.subtitle')}</p>\n </header>\n\n <PortsCard />\n\n {status.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : data ? (\n <div className=\"rounded-md border border-border bg-surface p-4\">\n <dl className=\"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-dim\">{t('service.modeLabel')}</dt>\n <dd>\n <Badge variant={MODE_VARIANT[data.mode]}>\n {t(`service.mode.${data.mode}`)}\n </Badge>\n </dd>\n {data.pid != null && (\n <>\n <dt className=\"text-text-dim\">{t('service.pidLabel')}</dt>\n <dd className=\"tabular-nums font-mono\">{data.pid}</dd>\n </>\n )}\n {data.uptime && (\n <>\n <dt className=\"text-text-dim\">{t('service.uptimeLabel')}</dt>\n <dd className=\"tabular-nums\">{data.uptime}</dd>\n </>\n )}\n {data.web && (\n <>\n <dt className=\"text-text-dim\">{t('service.webLabel')}</dt>\n <dd className=\"font-mono text-xs\">{data.web.bind}:{data.web.port}</dd>\n </>\n )}\n <dt className=\"text-text-dim\">{t('service.bootPhaseLabel')}</dt>\n <dd>\n <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs\">{data.bootPhase}</code>\n </dd>\n </dl>\n\n {/* Action buttons */}\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n disabled={isRunning || start.isPending}\n onClick={() => void onStart()}\n >\n {start.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Play className=\"h-4 w-4\" />}\n {t('service.actions.start')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!isRunning || restart.isPending}\n onClick={() => setConfirmRestart(true)}\n >\n <RotateCcw className={cn('h-4 w-4', restart.isPending && 'animate-spin')} />\n {t('service.actions.restart')}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n disabled={!isRunning || stop.isPending}\n onClick={() => setConfirmStop(true)}\n >\n <Square className=\"h-4 w-4\" />\n {t('service.actions.stop')}\n </Button>\n </div>\n </div>\n ) : null}\n\n <ConfirmDialog\n open={confirmStop}\n onOpenChange={setConfirmStop}\n title={t('service.actions.confirmStop')}\n description={t('service.actions.confirmStopDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.stop')}\n onConfirm={onConfirmStop}\n />\n <ConfirmDialog\n open={confirmRestart}\n onOpenChange={setConfirmRestart}\n title={t('service.actions.confirmRestart')}\n description={t('service.actions.confirmRestartDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.restart')}\n onConfirm={onConfirmRestart}\n />\n </div>\n )\n}\n\n/* ─────────────── Ports card (webPort + acpPort) ─────────────── */\n\n/** Validate a port string. Empty = \"use the default\", which we\n * represent on the wire as `undefined` (omitted field). Non-empty\n * must parse to 1..65535. */\nfunction parsePort(s: string): { ok: true; value: number | undefined } | { ok: false } {\n const trimmed = s.trim()\n if (!trimmed) return { ok: true, value: undefined }\n const n = Number.parseInt(trimmed, 10)\n if (!Number.isFinite(n) || n < 1 || n > 65535) return { ok: false }\n return { ok: true, value: n }\n}\n\nfunction PortsCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const updateCfg = useUpdateConfig()\n\n const cfg = cfgQuery.data\n const currentWeb = cfg?.webPort\n const currentAcp = cfg?.acpPort\n\n const [webDraft, setWebDraft] = useState<string>('')\n const [acpDraft, setAcpDraft] = useState<string>('')\n // Tracks the cfg snapshot we last synced from, so post-save refetch\n // re-hydrates the drafts cleanly (and so local edits don't get\n // clobbered by background refetches).\n const [syncedAt, setSyncedAt] = useState<number>(0)\n\n useEffect(() => {\n if (!cfg) return\n if (cfgQuery.dataUpdatedAt === syncedAt) return\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n setSyncedAt(cfgQuery.dataUpdatedAt)\n }, [cfg, cfgQuery.dataUpdatedAt, currentWeb, currentAcp, syncedAt])\n\n const webParsed = parsePort(webDraft)\n const acpParsed = parsePort(acpDraft)\n const webInvalid = !webParsed.ok\n const acpInvalid = !acpParsed.ok\n\n const isDirty = useMemo(() => {\n if (!cfg) return false\n const nextWeb = webParsed.ok ? webParsed.value : undefined\n const nextAcp = acpParsed.ok ? acpParsed.value : undefined\n return nextWeb !== currentWeb || nextAcp !== currentAcp\n }, [cfg, webParsed, acpParsed, currentWeb, currentAcp])\n\n function onDiscard(): void {\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n }\n\n async function onSave(): Promise<void> {\n if (!cfg || webInvalid || acpInvalid) return\n try {\n await updateCfg.mutateAsync({\n ...cfg,\n webPort: webParsed.ok ? webParsed.value : undefined,\n acpPort: acpParsed.ok ? acpParsed.value : undefined,\n })\n toast.success(t('service.ports.toast.saved'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n if (cfgQuery.isLoading) {\n return <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <Network className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('service.ports.title')}</h2>\n </header>\n <p className=\"px-4 pt-2 text-xs text-text-dim\">{t('service.ports.subtitle')}</p>\n\n <div className=\"grid grid-cols-1 gap-3 px-4 py-3 sm:grid-cols-2\">\n <PortField\n id=\"web-port\"\n label={t('service.ports.webPort')}\n hint={t('service.ports.webPortHint', { default: DEFAULT_WEB_PORT })}\n value={webDraft}\n onChange={setWebDraft}\n invalid={webInvalid}\n placeholder={String(DEFAULT_WEB_PORT)}\n />\n {/* R15 — acpPort hidden when remote-agent feature is off (same\n gate as the ACP card in /settings/agents). Server already\n strips acpPort from GET /api/config and drops it from\n incoming PUT in the off state. */}\n {cfg?.features?.remoteAgent ? (\n <PortField\n id=\"acp-port\"\n label={t('service.ports.acpPort')}\n hint={t('service.ports.acpPortHint', { default: DEFAULT_ACP_PORT })}\n value={acpDraft}\n onChange={setAcpDraft}\n invalid={acpInvalid}\n placeholder={String(DEFAULT_ACP_PORT)}\n />\n ) : null}\n </div>\n\n {isDirty && (\n <div className=\"flex items-center gap-2 border-t border-border px-4 py-3\">\n <Badge variant=\"warning\">{t('service.ports.restartRequired')}</Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('service.ports.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending || webInvalid || acpInvalid}\n >\n {updateCfg.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('service.ports.saving') : t('service.ports.save')}\n </Button>\n </div>\n )}\n </section>\n )\n}\n\ninterface PortFieldProps {\n id: string\n label: string\n hint: string\n value: string\n onChange: (v: string) => void\n invalid: boolean\n placeholder: string\n}\n\nfunction PortField({\n id, label, hint, value, onChange, invalid, placeholder,\n}: PortFieldProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor={id} className=\"text-xs font-medium\">{label}</Label>\n <Input\n id={id}\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={65535}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder}\n aria-invalid={invalid}\n className={cn('font-mono', invalid && 'border-danger focus:ring-danger')}\n />\n <p className={cn('text-[11px]', invalid ? 'text-danger' : 'text-text-dim')}>\n {invalid ? t('service.ports.invalidPort') : hint}\n </p>\n </div>\n )\n}\n"],"names":["Square","createLucideIcon","MODE_VARIANT","DEFAULT_WEB_PORT","DEFAULT_ACP_PORT","SettingsServiceRoute","t","useTranslation","status","useServiceStatus","data","isRunning","start","useStartService","stop","useStopService","restart","useRestartService","confirmStop","setConfirmStop","useState","confirmRestart","setConfirmRestart","onStart","toast","err","describeError","onConfirmStop","onConfirmRestart","jsxs","jsx","Button","Loader2","RefreshCcw","PortsCard","Badge","Fragment","Play","RotateCcw","cn","ConfirmDialog","parsePort","trimmed","n","cfgQuery","useConfig","updateCfg","useUpdateConfig","cfg","currentWeb","currentAcp","webDraft","setWebDraft","acpDraft","setAcpDraft","syncedAt","setSyncedAt","useEffect","webParsed","acpParsed","webInvalid","acpInvalid","isDirty","useMemo","nextWeb","nextAcp","onDiscard","onSave","Network","PortField","X","Save","id","label","hint","value","onChange","invalid","placeholder","Label","Input","e"],"mappings":"+kBAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAASC,EAAiB,SAAU,CACxC,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,CAChF,CAAC,EC4BKC,EAAgF,CACpF,QAAY,UACZ,WAAY,OACZ,WAAY,UACZ,KAAY,SACd,EAEMC,EAAmB,IACnBC,EAAmB,KAEzB,SAAwBC,IAAoC,CAC1D,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,WAAY,QAAQ,CAAC,EAC7CC,EAASC,EAAA,EACTC,EAAOF,EAAO,KACdG,EAAYD,GAAQA,EAAK,OAAS,OAElCE,EAAUC,EAAA,EACVC,EAAUC,EAAA,EACVC,EAAUC,EAAA,EAEV,CAACC,EAAaC,CAAc,EAAIC,EAAAA,SAAS,EAAK,EAC9C,CAACC,EAAgBC,CAAiB,EAAIF,EAAAA,SAAS,EAAK,EAE1D,eAAeG,GAAyB,CACtC,GAAI,CACF,MAAMX,EAAM,YAAA,EACZY,EAAM,QAAQlB,EAAE,uBAAuB,CAAC,CAC1C,OAASmB,EAAK,CACZD,EAAM,MAAME,EAAcD,EAAKnB,CAAC,EAAE,OAAO,CAC3C,CACF,CACA,eAAeqB,GAA+B,CAC5C,GAAI,CACF,MAAMb,EAAK,YAAA,EACXU,EAAM,QAAQlB,EAAE,uBAAuB,CAAC,CAC1C,OAASmB,EAAK,CACZD,MAAAA,EAAM,MAAME,EAAcD,EAAKnB,CAAC,EAAE,OAAO,EACnCmB,CACR,CACF,CACA,eAAeG,GAAkC,CAC/C,GAAI,CACF,MAAMZ,EAAQ,YAAA,EACdQ,EAAM,QAAQlB,EAAE,yBAAyB,CAAC,CAC5C,OAASmB,EAAK,CACZD,MAAAA,EAAM,MAAME,EAAcD,EAAKnB,CAAC,EAAE,OAAO,EACnCmB,CACR,CACF,CAEA,OACEI,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAxB,EAAE,eAAe,EAAE,EAC1DuB,EAAAA,KAACE,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAMvB,EAAO,QAAA,EACtB,SAAUA,EAAO,WACjB,aAAYF,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAE,EAAO,iBAAcwB,EAAA,CAAQ,UAAU,uBAAuB,EAAKF,EAAAA,IAACG,EAAA,CAAW,UAAU,SAAA,CAAU,EACpGH,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAxB,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,kBAAkB,CAAA,CAAE,CAAA,EAC9D,QAEC4B,EAAA,EAAU,EAEV1B,EAAO,UACNsB,EAAAA,IAAC,MAAA,CAAI,UAAU,4CAAA,CAA6C,EAC1DpB,EACFmB,EAAAA,KAAC,MAAA,CAAI,UAAU,iDACb,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,2DACZ,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,gBAAiB,SAAAxB,EAAE,mBAAmB,EAAE,EACtDwB,MAAC,KAAA,CACC,SAAAA,EAAAA,IAACK,EAAA,CAAM,QAASjC,EAAaQ,EAAK,IAAI,EACnC,WAAE,gBAAgBA,EAAK,IAAI,EAAE,EAChC,EACF,EACCA,EAAK,KAAO,MACXmB,EAAAA,KAAAO,EAAAA,SAAA,CACE,SAAA,CAAAN,MAAC,KAAA,CAAG,UAAU,gBAAiB,SAAAxB,EAAE,kBAAkB,EAAE,EACrDwB,EAAAA,IAAC,KAAA,CAAG,UAAU,yBAA0B,WAAK,GAAA,CAAI,CAAA,EACnD,EAEDpB,EAAK,QACJmB,EAAAA,KAAAO,EAAAA,SAAA,CACE,SAAA,CAAAN,MAAC,KAAA,CAAG,UAAU,gBAAiB,SAAAxB,EAAE,qBAAqB,EAAE,EACxDwB,EAAAA,IAAC,KAAA,CAAG,UAAU,eAAgB,WAAK,MAAA,CAAO,CAAA,EAC5C,EAEDpB,EAAK,KACJmB,EAAAA,KAAAO,EAAAA,SAAA,CACE,SAAA,CAAAN,MAAC,KAAA,CAAG,UAAU,gBAAiB,SAAAxB,EAAE,kBAAkB,EAAE,EACrDuB,EAAAA,KAAC,KAAA,CAAG,UAAU,oBAAqB,SAAA,CAAAnB,EAAK,IAAI,KAAK,IAAEA,EAAK,IAAI,IAAA,CAAA,CAAK,CAAA,EACnE,QAED,KAAA,CAAG,UAAU,gBAAiB,SAAAJ,EAAE,wBAAwB,EAAE,EAC3DwB,EAAAA,IAAC,MACC,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAU,6CAA8C,SAAApB,EAAK,UAAU,CAAA,CAC/E,CAAA,EACF,EAGAmB,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACb,SAAA,CAAAA,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,QAAQ,UACR,KAAK,KACL,SAAUpB,GAAaC,EAAM,UAC7B,QAAS,IAAM,KAAKW,EAAA,EAEnB,SAAA,CAAAX,EAAM,gBAAaoB,EAAA,CAAQ,UAAU,uBAAuB,EAAKF,EAAAA,IAACO,EAAA,CAAK,UAAU,SAAA,CAAU,EAC3F/B,EAAE,uBAAuB,CAAA,CAAA,CAAA,EAE5BuB,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,QAAQ,UACR,KAAK,KACL,SAAU,CAACpB,GAAaK,EAAQ,UAChC,QAAS,IAAMM,EAAkB,EAAI,EAErC,SAAA,CAAAQ,MAACQ,GAAU,UAAWC,EAAG,UAAWvB,EAAQ,WAAa,cAAc,EAAG,EACzEV,EAAE,yBAAyB,CAAA,CAAA,CAAA,EAE9BuB,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,QAAQ,cACR,KAAK,KACL,SAAU,CAACpB,GAAaG,EAAK,UAC7B,QAAS,IAAMK,EAAe,EAAI,EAElC,SAAA,CAAAW,EAAAA,IAAC9B,EAAA,CAAO,UAAU,SAAA,CAAU,EAC3BM,EAAE,sBAAsB,CAAA,CAAA,CAAA,CAC3B,CAAA,CACF,CAAA,CAAA,CACF,EACE,KAEJwB,EAAAA,IAACU,EAAA,CACC,KAAMtB,EACN,aAAcC,EACd,MAAOb,EAAE,6BAA6B,EACtC,YAAaA,EAAE,iCAAiC,EAChD,OAAO,SACP,aAAcA,EAAE,sBAAsB,EACtC,UAAWqB,CAAA,CAAA,EAEbG,EAAAA,IAACU,EAAA,CACC,KAAMnB,EACN,aAAcC,EACd,MAAOhB,EAAE,gCAAgC,EACzC,YAAaA,EAAE,oCAAoC,EACnD,OAAO,SACP,aAAcA,EAAE,yBAAyB,EACzC,UAAWsB,CAAA,CAAA,CACb,EACF,CAEJ,CAOA,SAASa,EAAU,EAAoE,CACrF,MAAMC,EAAU,EAAE,KAAA,EAClB,GAAI,CAACA,EAAS,MAAO,CAAE,GAAI,GAAM,MAAO,MAAA,EACxC,MAAMC,EAAI,OAAO,SAASD,EAAS,EAAE,EACrC,MAAI,CAAC,OAAO,SAASC,CAAC,GAAKA,EAAI,GAAKA,EAAI,MAAc,CAAE,GAAI,EAAA,EACrD,CAAE,GAAI,GAAM,MAAOA,CAAA,CAC5B,CAEA,SAAST,GAAyB,CAChC,KAAM,CAAE,EAAA5B,CAAA,EAAMC,EAAe,CAAC,WAAY,QAAQ,CAAC,EAC7CqC,EAAWC,EAAA,EACXC,EAAYC,EAAA,EAEZC,EAAMJ,EAAS,KACfK,EAAaD,GAAK,QAClBE,EAAaF,GAAK,QAElB,CAACG,EAAUC,CAAW,EAAIhC,EAAAA,SAAiB,EAAE,EAC7C,CAACiC,EAAUC,CAAW,EAAIlC,EAAAA,SAAiB,EAAE,EAI7C,CAACmC,EAAUC,CAAW,EAAIpC,EAAAA,SAAiB,CAAC,EAElDqC,EAAAA,UAAU,IAAM,CACTT,GACDJ,EAAS,gBAAkBW,IAC/BH,EAAYH,GAAc,KAAO,OAAOA,CAAU,EAAI,EAAE,EACxDK,EAAYJ,GAAc,KAAO,OAAOA,CAAU,EAAI,EAAE,EACxDM,EAAYZ,EAAS,aAAa,EACpC,EAAG,CAACI,EAAKJ,EAAS,cAAeK,EAAYC,EAAYK,CAAQ,CAAC,EAElE,MAAMG,EAAYjB,EAAUU,CAAQ,EAC9BQ,EAAYlB,EAAUY,CAAQ,EAC9BO,EAAa,CAACF,EAAU,GACxBG,EAAa,CAACF,EAAU,GAExBG,EAAUC,EAAAA,QAAQ,IAAM,CAC5B,GAAI,CAACf,EAAK,MAAO,GACjB,MAAMgB,EAAUN,EAAU,GAAKA,EAAU,MAAQ,OAC3CO,EAAUN,EAAU,GAAKA,EAAU,MAAQ,OACjD,OAAOK,IAAYf,GAAcgB,IAAYf,CAC/C,EAAG,CAACF,EAAKU,EAAWC,EAAWV,EAAYC,CAAU,CAAC,EAEtD,SAASgB,GAAkB,CACzBd,EAAYH,GAAc,KAAO,OAAOA,CAAU,EAAI,EAAE,EACxDK,EAAYJ,GAAc,KAAO,OAAOA,CAAU,EAAI,EAAE,CAC1D,CAEA,eAAeiB,GAAwB,CACrC,GAAI,GAACnB,GAAOY,GAAcC,GAC1B,GAAI,CACF,MAAMf,EAAU,YAAY,CAC1B,GAAGE,EACH,QAASU,EAAU,GAAKA,EAAU,MAAQ,OAC1C,QAASC,EAAU,GAAKA,EAAU,MAAQ,MAAA,CAC3C,EACDnC,EAAM,QAAQlB,EAAE,2BAA2B,CAAC,CAC9C,OAASmB,EAAK,CACZD,EAAM,MAAME,EAAcD,EAAKnB,CAAC,EAAE,OAAO,CAC3C,CACF,CAEA,OAAIsC,EAAS,UACJd,EAAAA,IAAC,MAAA,CAAI,UAAU,4CAAA,CAA6C,EAInED,EAAAA,KAAC,UAAA,CAAQ,UAAU,6CACjB,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,2DAChB,SAAA,CAAAC,EAAAA,IAACsC,EAAA,CAAQ,UAAU,uBAAA,CAAwB,QAC1C,KAAA,CAAG,UAAU,wBAAyB,SAAA9D,EAAE,qBAAqB,CAAA,CAAE,CAAA,EAClE,QACC,IAAA,CAAE,UAAU,kCAAmC,SAAAA,EAAE,wBAAwB,EAAE,EAE5EuB,EAAAA,KAAC,MAAA,CAAI,UAAU,kDACb,SAAA,CAAAC,EAAAA,IAACuC,EAAA,CACC,GAAG,WACH,MAAO/D,EAAE,uBAAuB,EAChC,KAAMA,EAAE,4BAA6B,CAAE,QAASH,EAAkB,EAClE,MAAOgD,EACP,SAAUC,EACV,QAASQ,EACT,YAAa,OAAOzD,CAAgB,CAAA,CAAA,EAMrC6C,GAAK,UAAU,YACdlB,EAAAA,IAACuC,EAAA,CACC,GAAG,WACH,MAAO/D,EAAE,uBAAuB,EAChC,KAAMA,EAAE,4BAA6B,CAAE,QAASF,EAAkB,EAClE,MAAOiD,EACP,SAAUC,EACV,QAASO,EACT,YAAa,OAAOzD,CAAgB,CAAA,CAAA,EAEpC,IAAA,EACN,EAEC0D,GACCjC,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACb,SAAA,CAAAC,MAACK,EAAA,CAAM,QAAQ,UAAW,SAAA7B,EAAE,+BAA+B,EAAE,EAC7DuB,EAAAA,KAACE,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAASmC,EACT,SAAUpB,EAAU,UAEpB,SAAA,CAAAhB,EAAAA,IAACwC,EAAA,CAAE,UAAU,SAAA,CAAU,EACtBhE,EAAE,uBAAuB,CAAA,CAAA,CAAA,EAE5BuB,EAAAA,KAACE,EAAA,CACC,KAAK,KACL,QAAS,IAAM,KAAKoC,EAAA,EACpB,SAAUrB,EAAU,WAAac,GAAcC,EAE9C,SAAA,CAAAf,EAAU,gBACNd,EAAA,CAAQ,UAAU,uBAAuB,EAC1CF,EAAAA,IAACyC,EAAA,CAAK,UAAU,SAAA,CAAU,EAC7BzB,EAAU,UAAYxC,EAAE,sBAAsB,EAAIA,EAAE,oBAAoB,CAAA,CAAA,CAAA,CAC3E,CAAA,CACF,CAAA,EAEJ,CAEJ,CAYA,SAAS+D,EAAU,CACjB,GAAAG,EAAI,MAAAC,EAAO,KAAAC,EAAM,MAAAC,EAAO,SAAAC,EAAU,QAAAC,EAAS,YAAAC,CAC7C,EAAgC,CAC9B,KAAM,CAAE,EAAAxE,CAAA,EAAMC,EAAe,UAAU,EACvC,OACEsB,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAC,MAACiD,EAAA,CAAM,QAASP,EAAI,UAAU,sBAAuB,SAAAC,EAAM,EAC3D3C,EAAAA,IAACkD,EAAA,CACC,GAAAR,EACA,KAAK,SACL,UAAU,UACV,IAAK,EACL,IAAK,MACL,MAAAG,EACA,SAAWM,GAAML,EAASK,EAAE,OAAO,KAAK,EACxC,YAAAH,EACA,eAAcD,EACd,UAAWtC,EAAG,YAAasC,GAAW,iCAAiC,CAAA,CAAA,EAEzE/C,EAAAA,IAAC,IAAA,CAAE,UAAWS,EAAG,cAAesC,EAAU,cAAgB,eAAe,EACtE,SAAAA,EAAUvE,EAAE,2BAA2B,EAAIoE,CAAA,CAC9C,CAAA,EACF,CAEJ","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"service-A0Hzear0.js","sources":["../../node_modules/lucide-react/dist/esm/icons/square.js","../../src/routes/settings/service.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Square = createLucideIcon(\"Square\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n]);\n\nexport { Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * /settings/service — operator-facing process control: see the\n * running agim daemon's mode/pid/uptime + start, stop, or restart it.\n *\n * R8 (this round) added a dedicated \"Ports\" card at the top covering\n * webPort + acpPort. They live in `~/.agim/config.json` (PUT /api/config),\n * and take effect on the next service restart — handled by the\n * Start/Restart buttons immediately below.\n *\n * Stop and restart go through ConfirmDialog because they\n * permanently interrupt every messenger adapter + in-flight job;\n * Start is one-click since it's safe to invoke even when already\n * running (backend short-circuits to alreadyRunning:true).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n Loader2, Network, Play, RefreshCcw, RotateCcw, Save, Square, X,\n} from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n useConfig,\n useRestartService,\n useServiceStatus,\n useStartService,\n useStopService,\n useUpdateConfig,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { ServiceMode } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst MODE_VARIANT: Record<ServiceMode, 'success' | 'info' | 'warning' | 'default'> = {\n systemd: 'success',\n background: 'info',\n foreground: 'warning',\n none: 'default',\n}\n\nconst DEFAULT_WEB_PORT = 3000\nconst DEFAULT_ACP_PORT = 9090\n\nexport default function SettingsServiceRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const status = useServiceStatus()\n const data = status.data\n const isRunning = data && data.mode !== 'none'\n\n const start = useStartService()\n const stop = useStopService()\n const restart = useRestartService()\n\n const [confirmStop, setConfirmStop] = useState(false)\n const [confirmRestart, setConfirmRestart] = useState(false)\n\n async function onStart(): Promise<void> {\n try {\n await start.mutateAsync()\n toast.success(t('service.toast.started'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n async function onConfirmStop(): Promise<void> {\n try {\n await stop.mutateAsync()\n toast.success(t('service.toast.stopped'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n async function onConfirmRestart(): Promise<void> {\n try {\n await restart.mutateAsync()\n toast.success(t('service.toast.restarted'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-3xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('service.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => status.refetch()}\n disabled={status.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {status.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('service.subtitle')}</p>\n </header>\n\n <PortsCard />\n\n {status.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : data ? (\n <div className=\"rounded-md border border-border bg-surface p-4\">\n <dl className=\"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-dim\">{t('service.modeLabel')}</dt>\n <dd>\n <Badge variant={MODE_VARIANT[data.mode]}>\n {t(`service.mode.${data.mode}`)}\n </Badge>\n </dd>\n {data.pid != null && (\n <>\n <dt className=\"text-text-dim\">{t('service.pidLabel')}</dt>\n <dd className=\"tabular-nums font-mono\">{data.pid}</dd>\n </>\n )}\n {data.uptime && (\n <>\n <dt className=\"text-text-dim\">{t('service.uptimeLabel')}</dt>\n <dd className=\"tabular-nums\">{data.uptime}</dd>\n </>\n )}\n {data.web && (\n <>\n <dt className=\"text-text-dim\">{t('service.webLabel')}</dt>\n <dd className=\"font-mono text-xs\">{data.web.bind}:{data.web.port}</dd>\n </>\n )}\n <dt className=\"text-text-dim\">{t('service.bootPhaseLabel')}</dt>\n <dd>\n <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs\">{data.bootPhase}</code>\n </dd>\n </dl>\n\n {/* Action buttons */}\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n disabled={isRunning || start.isPending}\n onClick={() => void onStart()}\n >\n {start.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Play className=\"h-4 w-4\" />}\n {t('service.actions.start')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!isRunning || restart.isPending}\n onClick={() => setConfirmRestart(true)}\n >\n <RotateCcw className={cn('h-4 w-4', restart.isPending && 'animate-spin')} />\n {t('service.actions.restart')}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n disabled={!isRunning || stop.isPending}\n onClick={() => setConfirmStop(true)}\n >\n <Square className=\"h-4 w-4\" />\n {t('service.actions.stop')}\n </Button>\n </div>\n </div>\n ) : null}\n\n <ConfirmDialog\n open={confirmStop}\n onOpenChange={setConfirmStop}\n title={t('service.actions.confirmStop')}\n description={t('service.actions.confirmStopDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.stop')}\n onConfirm={onConfirmStop}\n />\n <ConfirmDialog\n open={confirmRestart}\n onOpenChange={setConfirmRestart}\n title={t('service.actions.confirmRestart')}\n description={t('service.actions.confirmRestartDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.restart')}\n onConfirm={onConfirmRestart}\n />\n </div>\n )\n}\n\n/* ─────────────── Ports card (webPort + acpPort) ─────────────── */\n\n/** Validate a port string. Empty = \"use the default\", which we\n * represent on the wire as `undefined` (omitted field). Non-empty\n * must parse to 1..65535. */\nfunction parsePort(s: string): { ok: true; value: number | undefined } | { ok: false } {\n const trimmed = s.trim()\n if (!trimmed) return { ok: true, value: undefined }\n const n = Number.parseInt(trimmed, 10)\n if (!Number.isFinite(n) || n < 1 || n > 65535) return { ok: false }\n return { ok: true, value: n }\n}\n\nfunction PortsCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const updateCfg = useUpdateConfig()\n\n const cfg = cfgQuery.data\n const currentWeb = cfg?.webPort\n const currentAcp = cfg?.acpPort\n\n const [webDraft, setWebDraft] = useState<string>('')\n const [acpDraft, setAcpDraft] = useState<string>('')\n // Tracks the cfg snapshot we last synced from, so post-save refetch\n // re-hydrates the drafts cleanly (and so local edits don't get\n // clobbered by background refetches).\n const [syncedAt, setSyncedAt] = useState<number>(0)\n\n useEffect(() => {\n if (!cfg) return\n if (cfgQuery.dataUpdatedAt === syncedAt) return\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n setSyncedAt(cfgQuery.dataUpdatedAt)\n }, [cfg, cfgQuery.dataUpdatedAt, currentWeb, currentAcp, syncedAt])\n\n const webParsed = parsePort(webDraft)\n const acpParsed = parsePort(acpDraft)\n const webInvalid = !webParsed.ok\n const acpInvalid = !acpParsed.ok\n\n const isDirty = useMemo(() => {\n if (!cfg) return false\n const nextWeb = webParsed.ok ? webParsed.value : undefined\n const nextAcp = acpParsed.ok ? acpParsed.value : undefined\n return nextWeb !== currentWeb || nextAcp !== currentAcp\n }, [cfg, webParsed, acpParsed, currentWeb, currentAcp])\n\n function onDiscard(): void {\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n }\n\n async function onSave(): Promise<void> {\n if (!cfg || webInvalid || acpInvalid) return\n try {\n await updateCfg.mutateAsync({\n ...cfg,\n webPort: webParsed.ok ? webParsed.value : undefined,\n acpPort: acpParsed.ok ? acpParsed.value : undefined,\n })\n toast.success(t('service.ports.toast.saved'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n if (cfgQuery.isLoading) {\n return <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <Network className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('service.ports.title')}</h2>\n </header>\n <p className=\"px-4 pt-2 text-xs text-text-dim\">{t('service.ports.subtitle')}</p>\n\n <div className=\"grid grid-cols-1 gap-3 px-4 py-3 sm:grid-cols-2\">\n <PortField\n id=\"web-port\"\n label={t('service.ports.webPort')}\n hint={t('service.ports.webPortHint', { default: DEFAULT_WEB_PORT })}\n value={webDraft}\n onChange={setWebDraft}\n invalid={webInvalid}\n placeholder={String(DEFAULT_WEB_PORT)}\n />\n {/* R15 — acpPort hidden when remote-agent feature is off (same\n gate as the ACP card in /settings/agents). Server already\n strips acpPort from GET /api/config and drops it from\n incoming PUT in the off state. */}\n {cfg?.features?.remoteAgent ? (\n <PortField\n id=\"acp-port\"\n label={t('service.ports.acpPort')}\n hint={t('service.ports.acpPortHint', { default: DEFAULT_ACP_PORT })}\n value={acpDraft}\n onChange={setAcpDraft}\n invalid={acpInvalid}\n placeholder={String(DEFAULT_ACP_PORT)}\n />\n ) : null}\n </div>\n\n {isDirty && (\n <div className=\"flex items-center gap-2 border-t border-border px-4 py-3\">\n <Badge variant=\"warning\">{t('service.ports.restartRequired')}</Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('service.ports.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending || webInvalid || acpInvalid}\n >\n {updateCfg.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('service.ports.saving') : t('service.ports.save')}\n </Button>\n </div>\n )}\n </section>\n )\n}\n\ninterface PortFieldProps {\n id: string\n label: string\n hint: string\n value: string\n onChange: (v: string) => void\n invalid: boolean\n placeholder: string\n}\n\nfunction PortField({\n id, label, hint, value, onChange, invalid, placeholder,\n}: PortFieldProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor={id} className=\"text-xs font-medium\">{label}</Label>\n <Input\n id={id}\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={65535}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder}\n aria-invalid={invalid}\n className={cn('font-mono', invalid && 'border-danger focus:ring-danger')}\n />\n <p className={cn('text-[11px]', invalid ? 'text-danger' : 'text-text-dim')}>\n {invalid ? t('service.ports.invalidPort') : hint}\n </p>\n </div>\n )\n}\n"],"names":["Square","createLucideIcon","MODE_VARIANT","DEFAULT_WEB_PORT","DEFAULT_ACP_PORT","SettingsServiceRoute","t","useTranslation","status","useServiceStatus","data","isRunning","start","useStartService","stop","useStopService","restart","useRestartService","confirmStop","setConfirmStop","useState","confirmRestart","setConfirmRestart","onStart","toast","err","describeError","onConfirmStop","onConfirmRestart","jsxs","jsx","Button","Loader2","RefreshCcw","PortsCard","Badge","Fragment","Play","RotateCcw","cn","ConfirmDialog","parsePort","trimmed","n","cfgQuery","useConfig","updateCfg","useUpdateConfig","cfg","currentWeb","currentAcp","webDraft","setWebDraft","acpDraft","setAcpDraft","syncedAt","setSyncedAt","useEffect","webParsed","acpParsed","webInvalid","acpInvalid","isDirty","useMemo","nextWeb","nextAcp","onDiscard","onSave","Network","PortField","X","Save","id","label","hint","value","onChange","invalid","placeholder","Label","Input","e"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,7 +1,7 @@
1
- import{n as e}from"./index-O0BQoyzo.js";/**
1
+ import{n as e}from"./index-DEWFfW_Z.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const t=e("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);export{t as S};
7
- //# sourceMappingURL=shield-alert-CKFVsGgI.js.map
7
+ //# sourceMappingURL=shield-alert-DrnN6fz_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shield-alert-CKFVsGgI.js","sources":["../../node_modules/lucide-react/dist/esm/icons/shield-alert.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldAlert = createLucideIcon(\"ShieldAlert\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }]\n]);\n\nexport { ShieldAlert as default };\n//# sourceMappingURL=shield-alert.js.map\n"],"names":["ShieldAlert","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAcC,EAAiB,cAAe,CAClD,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"shield-alert-DrnN6fz_.js","sources":["../../node_modules/lucide-react/dist/esm/icons/shield-alert.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldAlert = createLucideIcon(\"ShieldAlert\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }]\n]);\n\nexport { ShieldAlert as default };\n//# sourceMappingURL=shield-alert.js.map\n"],"names":["ShieldAlert","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAcC,EAAiB,cAAe,CAClD,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
@@ -1,2 +1,2 @@
1
- import{j as r,k as c}from"./index-O0BQoyzo.js";const i={succeeded:"success",completed:"success",done:"success",approved:"success",allowed:"success",delivered:"success",active:"success",running:"info",in_progress:"info",pending:"info",queued:"info",scheduled:"info",open:"info",paused:"warning",awaiting:"warning",timeout:"warning",expired:"warning",failed:"danger",error:"danger",denied:"danger",rejected:"danger",cancelled:"danger",canceled:"danger",finished:"default",closed:"default",archived:"default"};function o({status:e,variant:n,children:d,...s}){const a=n??i[e.toLowerCase()]??"default";return r.jsx(c,{variant:a,...s,children:d??e})}o.displayName="StatusBadge";export{o as S};
2
- //# sourceMappingURL=status-badge-BSkpyN4D.js.map
1
+ import{j as r,k as c}from"./index-DEWFfW_Z.js";const i={succeeded:"success",completed:"success",done:"success",approved:"success",allowed:"success",delivered:"success",active:"success",running:"info",in_progress:"info",pending:"info",queued:"info",scheduled:"info",open:"info",paused:"warning",awaiting:"warning",timeout:"warning",expired:"warning",failed:"danger",error:"danger",denied:"danger",rejected:"danger",cancelled:"danger",canceled:"danger",finished:"default",closed:"default",archived:"default"};function o({status:e,variant:n,children:d,...s}){const a=n??i[e.toLowerCase()]??"default";return r.jsx(c,{variant:a,...s,children:d??e})}o.displayName="StatusBadge";export{o as S};
2
+ //# sourceMappingURL=status-badge-Ryzf96Pl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-badge-BSkpyN4D.js","sources":["../../src/components/common/status-badge.tsx"],"sourcesContent":["/**\n * StatusBadge — domain status string → Badge variant + label.\n *\n * Single source of truth for the color mapping across the 4 M2 pages\n * (jobs / approvals / reminders / memos) plus the M3 observability\n * page. Without this every page would invent its own (job status\n * \"running\" mapped to \"warning\" on tasks.html, \"info\" on approvals.\n * html, \"secondary\" on observability — the kind of drift the v2\n * rewrite is supposed to eliminate).\n *\n * The label slot is intentionally a child rather than a prop: callers\n * pass i18n'd strings via `<StatusBadge status=\"running\">{t('jobs.\n * status.running')}</StatusBadge>` so the badge stays language-aware\n * without needing useTranslation here.\n *\n * Unknown status falls back to `default` variant (neutral gray pill)\n * so a backend that introduces a new state doesn't crash the page.\n */\n\nimport * as React from 'react'\nimport { Badge, type BadgeProps } from '@/components/ui/badge'\n\n/**\n * Status palette shared across domain entities. The mapping is\n * deliberately broad — both \"succeeded\" and \"completed\" land on\n * success; both \"running\" and \"in_progress\" land on info, etc. —\n * because the backend hasn't been canonicalised yet (memory.ts uses\n * one set, jobs.ts another).\n */\nconst STATUS_VARIANT: Record<string, BadgeProps['variant']> = {\n // Success-family\n succeeded: 'success',\n completed: 'success',\n done: 'success',\n approved: 'success',\n allowed: 'success',\n delivered: 'success',\n active: 'success',\n\n // In-flight\n running: 'info',\n in_progress:'info',\n pending: 'info',\n queued: 'info',\n scheduled: 'info',\n open: 'info',\n\n // Warnings (operator may need to look)\n paused: 'warning',\n awaiting: 'warning',\n timeout: 'warning',\n expired: 'warning',\n\n // Failed / errored\n failed: 'danger',\n error: 'danger',\n denied: 'danger',\n rejected: 'danger',\n cancelled: 'danger',\n canceled: 'danger',\n\n // Terminal-neutral\n finished: 'default',\n closed: 'default',\n archived: 'default',\n}\n\nexport interface StatusBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n status: string\n children?: React.ReactNode\n /** Force-override the auto-mapped variant. */\n variant?: BadgeProps['variant']\n}\n\nfunction StatusBadge({\n status,\n variant,\n children,\n ...rest\n}: StatusBadgeProps): JSX.Element {\n const resolved = variant ?? STATUS_VARIANT[status.toLowerCase()] ?? 'default'\n return (\n <Badge variant={resolved} {...rest}>\n {children ?? status}\n </Badge>\n )\n}\nStatusBadge.displayName = 'StatusBadge'\n\nexport { StatusBadge, STATUS_VARIANT }\n"],"names":["STATUS_VARIANT","StatusBadge","status","variant","children","rest","resolved","Badge"],"mappings":"+CA6BA,MAAMA,EAAwD,CAE5D,UAAY,UACZ,UAAY,UACZ,KAAY,UACZ,SAAY,UACZ,QAAY,UACZ,UAAY,UACZ,OAAY,UAGZ,QAAY,OACZ,YAAY,OACZ,QAAY,OACZ,OAAY,OACZ,UAAY,OACZ,KAAY,OAGZ,OAAY,UACZ,SAAY,UACZ,QAAY,UACZ,QAAY,UAGZ,OAAY,SACZ,MAAY,SACZ,OAAY,SACZ,SAAY,SACZ,UAAY,SACZ,SAAY,SAGZ,SAAY,UACZ,OAAY,UACZ,SAAY,SACd,EASA,SAASC,EAAY,CACnB,OAAAC,EACA,QAAAC,EACA,SAAAC,EACA,GAAGC,CACL,EAAkC,CAChC,MAAMC,EAAWH,GAAWH,EAAeE,EAAO,YAAA,CAAa,GAAK,UACpE,aACGK,EAAA,CAAM,QAASD,EAAW,GAAGD,EAC3B,YAAYH,EACf,CAEJ,CACAD,EAAY,YAAc"}
1
+ {"version":3,"file":"status-badge-Ryzf96Pl.js","sources":["../../src/components/common/status-badge.tsx"],"sourcesContent":["/**\n * StatusBadge — domain status string → Badge variant + label.\n *\n * Single source of truth for the color mapping across the 4 M2 pages\n * (jobs / approvals / reminders / memos) plus the M3 observability\n * page. Without this every page would invent its own (job status\n * \"running\" mapped to \"warning\" on tasks.html, \"info\" on approvals.\n * html, \"secondary\" on observability — the kind of drift the v2\n * rewrite is supposed to eliminate).\n *\n * The label slot is intentionally a child rather than a prop: callers\n * pass i18n'd strings via `<StatusBadge status=\"running\">{t('jobs.\n * status.running')}</StatusBadge>` so the badge stays language-aware\n * without needing useTranslation here.\n *\n * Unknown status falls back to `default` variant (neutral gray pill)\n * so a backend that introduces a new state doesn't crash the page.\n */\n\nimport * as React from 'react'\nimport { Badge, type BadgeProps } from '@/components/ui/badge'\n\n/**\n * Status palette shared across domain entities. The mapping is\n * deliberately broad — both \"succeeded\" and \"completed\" land on\n * success; both \"running\" and \"in_progress\" land on info, etc. —\n * because the backend hasn't been canonicalised yet (memory.ts uses\n * one set, jobs.ts another).\n */\nconst STATUS_VARIANT: Record<string, BadgeProps['variant']> = {\n // Success-family\n succeeded: 'success',\n completed: 'success',\n done: 'success',\n approved: 'success',\n allowed: 'success',\n delivered: 'success',\n active: 'success',\n\n // In-flight\n running: 'info',\n in_progress:'info',\n pending: 'info',\n queued: 'info',\n scheduled: 'info',\n open: 'info',\n\n // Warnings (operator may need to look)\n paused: 'warning',\n awaiting: 'warning',\n timeout: 'warning',\n expired: 'warning',\n\n // Failed / errored\n failed: 'danger',\n error: 'danger',\n denied: 'danger',\n rejected: 'danger',\n cancelled: 'danger',\n canceled: 'danger',\n\n // Terminal-neutral\n finished: 'default',\n closed: 'default',\n archived: 'default',\n}\n\nexport interface StatusBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n status: string\n children?: React.ReactNode\n /** Force-override the auto-mapped variant. */\n variant?: BadgeProps['variant']\n}\n\nfunction StatusBadge({\n status,\n variant,\n children,\n ...rest\n}: StatusBadgeProps): JSX.Element {\n const resolved = variant ?? STATUS_VARIANT[status.toLowerCase()] ?? 'default'\n return (\n <Badge variant={resolved} {...rest}>\n {children ?? status}\n </Badge>\n )\n}\nStatusBadge.displayName = 'StatusBadge'\n\nexport { StatusBadge, STATUS_VARIANT }\n"],"names":["STATUS_VARIANT","StatusBadge","status","variant","children","rest","resolved","Badge"],"mappings":"+CA6BA,MAAMA,EAAwD,CAE5D,UAAY,UACZ,UAAY,UACZ,KAAY,UACZ,SAAY,UACZ,QAAY,UACZ,UAAY,UACZ,OAAY,UAGZ,QAAY,OACZ,YAAY,OACZ,QAAY,OACZ,OAAY,OACZ,UAAY,OACZ,KAAY,OAGZ,OAAY,UACZ,SAAY,UACZ,QAAY,UACZ,QAAY,UAGZ,OAAY,SACZ,MAAY,SACZ,OAAY,SACZ,SAAY,SACZ,UAAY,SACZ,SAAY,SAGZ,SAAY,UACZ,OAAY,UACZ,SAAY,SACd,EASA,SAASC,EAAY,CACnB,OAAAC,EACA,QAAAC,EACA,SAAAC,EACA,GAAGC,CACL,EAAkC,CAChC,MAAMC,EAAWH,GAAWH,EAAeE,EAAO,YAAA,CAAa,GAAK,UACpE,aACGK,EAAA,CAAM,QAASD,EAAW,GAAGD,EAC3B,YAAYH,EACf,CAEJ,CACAD,EAAY,YAAc"}
@@ -1,7 +1,7 @@
1
- import{n as g,a as b,d as j,u as k,e as N,j as s,c as y,B as w,L as S,I as v}from"./index-O0BQoyzo.js";import{r as C}from"./react-Cb2sDjhD.js";import{D as L}from"./data-table-S7rIjwdO.js";import{E as T}from"./empty-state-C-qjOHyu.js";import{S as I}from"./status-badge-BSkpyN4D.js";import{u as A}from"./useQuery-PdiC7-sY.js";import{u as D}from"./use-event-stream-DgGpGKop.js";import{L as M}from"./loader-circle-9VUMGitw.js";import{R as E}from"./refresh-ccw-D2CWiyU_.js";import"./table-CPn1MRcy.js";import"./arrow-up-63xELY5Q.js";import"./arrow-down-BXvC8Al2.js";/**
1
+ import{n as g,a as b,d as j,u as k,e as N,j as s,c as y,B as w,L as S,I as v}from"./index-DEWFfW_Z.js";import{r as C}from"./react-DlP5eolq.js";import{D as L}from"./data-table-DswkWUfG.js";import{E as T}from"./empty-state-D9Hi0Atm.js";import{S as I}from"./status-badge-Ryzf96Pl.js";import{u as A}from"./useQuery-CY2iazjN.js";import{u as D}from"./use-event-stream-I1lMFEfh.js";import{L as M}from"./loader-circle-Bbw4pEyE.js";import{R as E}from"./refresh-ccw-uNKeBeRl.js";import"./table-BbAOSyc8.js";import"./arrow-up-BOADc9ce.js";import"./arrow-down-SLWKqtDc.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const R=g("ListTree",[["path",{d:"M21 12h-8",key:"1bmf0i"}],["path",{d:"M21 6H8",key:"1pqkrb"}],["path",{d:"M21 18h-8",key:"1tm79t"}],["path",{d:"M3 6v4c0 1.1.9 2 2 2h3",key:"1ywdgy"}],["path",{d:"M3 10v6c0 1.1.9 2 2 2h3",key:"2wc746"}]]),m={all:["subtasks"],list:e=>["subtasks","list",e]};function q(e){return A({queryKey:m.list(e),queryFn:()=>j.listSubtasks(e)})}function F(){const e=b();return()=>e.invalidateQueries({queryKey:m.all})}const $={connected:"text-success",connecting:"text-text-dim",reconnecting:"text-warning",closed:"text-text-muted"};function X(){const{t:e}=k(["tasks","common"]),[a,n]=N(),r=F(),i=a.get("agent")??"",{data:d,isLoading:u,isFetching:c,refetch:x}=q(i?{agent:i}:{}),p=d?.subtasks??[],o=D({job:()=>r()});function h(t){const l=new URLSearchParams(a);t?l.set("agent",t):l.delete("agent"),n(l,{replace:!0})}const f=C.useMemo(()=>[{id:"id",header:e("subtasks.col.id"),cell:t=>s.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",t.id]}),headClassName:"w-16"},{id:"agent",header:e("subtasks.col.agent"),cell:t=>s.jsx("span",{className:"font-medium",children:t.agent}),headClassName:"w-32"},{id:"prompt",header:e("subtasks.col.prompt"),cell:t=>s.jsx("span",{className:"line-clamp-2 text-text-dim",children:t.prompt}),asCardTitle:!0},{id:"status",header:e("subtasks.col.status"),cell:t=>s.jsx(I,{status:t.status,children:e(`subtasks.status.${t.status}`,{defaultValue:t.status})}),headClassName:"w-32"},{id:"parent",header:e("subtasks.col.parent"),cell:t=>s.jsxs("span",{className:"text-text-dim",children:[s.jsx("span",{className:"font-medium text-text",children:t.parentAgent}),s.jsx("span",{className:"text-text-muted",children:" / "}),s.jsx("span",{title:t.parentSessionId,children:t.parentSessionId.slice(0,8)})]}),headClassName:"w-40"},{id:"platform",header:e("subtasks.col.platform"),cell:t=>s.jsx("span",{className:"text-text-dim",children:t.platform}),headClassName:"w-28",hideOnMobile:!0},{id:"createdAt",header:e("subtasks.col.createdAt"),cell:t=>s.jsx("span",{className:"text-text-dim",children:B(t.createdAt)}),headClassName:"w-40",hideOnMobile:!0}],[e]);return s.jsxs("div",{className:"mx-auto flex max-w-7xl flex-col gap-4",children:[s.jsxs("header",{className:"flex flex-col gap-1",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[s.jsx("h1",{className:"text-xl font-semibold",children:e("subtasks.title")}),s.jsx("span",{className:y("text-xs font-medium tabular-nums",$[o]),children:e(`jobs.live.${o}`)}),s.jsxs(w,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>x(),disabled:c,"aria-label":e("actions.refresh",{ns:"common"}),children:[c?s.jsx(M,{className:"h-4 w-4 animate-spin"}):s.jsx(E,{className:"h-4 w-4"}),s.jsx("span",{className:"hidden sm:inline",children:e("actions.refresh",{ns:"common"})})]})]}),s.jsx("p",{className:"text-sm text-text-dim",children:e("subtasks.subtitle")})]}),s.jsx("div",{className:"flex flex-wrap items-end gap-2",children:s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsx(S,{htmlFor:"agent-filter",className:"text-xs text-text-dim",children:e("subtasks.filter.agent")}),s.jsx(v,{id:"agent-filter",value:i,onChange:t=>h(t.target.value),placeholder:e("subtasks.filter.agentAny"),className:"w-48"})]})}),s.jsx(L,{columns:f,rows:p,getRowId:t=>`${t.parentSessionId}:${t.id}`,loading:u,emptyState:s.jsx(T,{icon:s.jsx(R,{}),title:e("subtasks.empty.title"),description:e("subtasks.empty.description")})})]})}function B(e){try{const a=new Date(e);if(Number.isNaN(a.getTime()))return e;const n=new Date;return a.toDateString()===n.toDateString()?a.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"}):a.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}export{X as default};
7
- //# sourceMappingURL=subtasks-Bel-I1Sk.js.map
7
+ //# sourceMappingURL=subtasks-Bzh3o3EF.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"subtasks-Bel-I1Sk.js","sources":["../../node_modules/lucide-react/dist/esm/icons/list-tree.js","../../src/hooks/use-subtasks.ts","../../src/routes/tasks/subtasks.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ListTree = createLucideIcon(\"ListTree\", [\n [\"path\", { d: \"M21 12h-8\", key: \"1bmf0i\" }],\n [\"path\", { d: \"M21 6H8\", key: \"1pqkrb\" }],\n [\"path\", { d: \"M21 18h-8\", key: \"1tm79t\" }],\n [\"path\", { d: \"M3 6v4c0 1.1.9 2 2 2h3\", key: \"1ywdgy\" }],\n [\"path\", { d: \"M3 10v6c0 1.1.9 2 2 2h3\", key: \"2wc746\" }]\n]);\n\nexport { ListTree as default };\n//# sourceMappingURL=list-tree.js.map\n","/**\n * useSubtasks — react-query wrapper for /api/subtasks.\n *\n * Subtasks are a flattened view of session.subtasks across every\n * conversation file in ~/.agim/sessions/. The endpoint is read-only\n * — no cancel / re-run mutation surface (yet). Live refresh rides on\n * the same SSE 'job' event (subtask state changes piggy-back on the\n * parent job's lifecycle).\n */\n\nimport { useQueryClient, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { ListSubtasksQuery, ListSubtasksResponse } from '@/types/api'\n\nexport const subtasksKeys = {\n all: ['subtasks'] as const,\n list: (q: ListSubtasksQuery) => ['subtasks', 'list', q] as const,\n}\n\nexport function useSubtasks(query: ListSubtasksQuery) {\n return useQuery<ListSubtasksResponse>({\n queryKey: subtasksKeys.list(query),\n queryFn: () => api.listSubtasks(query),\n })\n}\n\nexport function useInvalidateSubtasks() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: subtasksKeys.all })\n}\n","/**\n * /tasks/subtasks — flattened view of per-conversation child tasks\n * spawned by parent agents.\n *\n * Read-only: the backend doesn't expose cancel / re-run for subtasks\n * separately from the parent session. The page mirrors the columns\n * of /tasks/jobs but adds parent context (agent + platform) and\n * drops the duration / cost columns (which session.subtasks doesn't\n * track per-subtask).\n *\n * SSE: subscribes to the same `job` event as /tasks/jobs — subtask\n * status changes piggy-back on the parent job lifecycle in the\n * backend's event-bus.\n */\n\nimport { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Loader2, ListTree, RefreshCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { useSubtasks, useInvalidateSubtasks } from '@/hooks/use-subtasks'\nimport { useEventStream, type SseStatus } from '@/hooks/use-event-stream'\nimport type { Subtask } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst LIVE_STATUS_CLASS: Record<SseStatus, string> = {\n connected: 'text-success',\n connecting: 'text-text-dim',\n reconnecting: 'text-warning',\n closed: 'text-text-muted',\n}\n\nexport default function SubtasksRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const invalidate = useInvalidateSubtasks()\n const agent = params.get('agent') ?? ''\n\n const { data, isLoading, isFetching, refetch } = useSubtasks(\n agent ? { agent } : {},\n )\n const subtasks = data?.subtasks ?? []\n\n const live = useEventStream({\n job: () => invalidate(),\n })\n\n function setAgentFilter(v: string): void {\n const next = new URLSearchParams(params)\n if (!v) next.delete('agent')\n else next.set('agent', v)\n setParams(next, { replace: true })\n }\n\n const columns: DataTableColumn<Subtask>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('subtasks.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'agent',\n header: t('subtasks.col.agent'),\n cell: (r) => <span className=\"font-medium\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'prompt',\n header: t('subtasks.col.prompt'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.prompt}</span>,\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('subtasks.col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`subtasks.status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-32',\n },\n {\n id: 'parent',\n header: t('subtasks.col.parent'),\n cell: (r) => (\n <span className=\"text-text-dim\">\n <span className=\"font-medium text-text\">{r.parentAgent}</span>\n <span className=\"text-text-muted\"> / </span>\n <span title={r.parentSessionId}>{r.parentSessionId.slice(0, 8)}</span>\n </span>\n ),\n headClassName: 'w-40',\n },\n {\n id: 'platform',\n header: t('subtasks.col.platform'),\n cell: (r) => <span className=\"text-text-dim\">{r.platform}</span>,\n headClassName: 'w-28',\n hideOnMobile: true,\n },\n {\n id: 'createdAt',\n header: t('subtasks.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.createdAt)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('subtasks.title')}</h1>\n <span className={cn('text-xs font-medium tabular-nums', LIVE_STATUS_CLASS[live])}>\n {t(`jobs.live.${live}`)}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('subtasks.subtitle')}</p>\n </header>\n\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"agent-filter\" className=\"text-xs text-text-dim\">\n {t('subtasks.filter.agent')}\n </Label>\n <Input\n id=\"agent-filter\"\n value={agent}\n onChange={(e) => setAgentFilter(e.target.value)}\n placeholder={t('subtasks.filter.agentAny')}\n className=\"w-48\"\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n rows={subtasks}\n getRowId={(r) => `${r.parentSessionId}:${r.id}`}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<ListTree />}\n title={t('subtasks.empty.title')}\n description={t('subtasks.empty.description')}\n />\n }\n />\n </div>\n )\n}\n\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const now = new Date()\n const sameDay = d.toDateString() === now.toDateString()\n if (sameDay) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit' })\n }\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["ListTree","createLucideIcon","subtasksKeys","q","useSubtasks","query","useQuery","api","useInvalidateSubtasks","qc","useQueryClient","LIVE_STATUS_CLASS","SubtasksRoute","t","useTranslation","params","setParams","useSearchParams","invalidate","agent","data","isLoading","isFetching","refetch","subtasks","live","useEventStream","setAgentFilter","v","next","columns","useMemo","r","jsxs","jsx","StatusBadge","formatTime","cn","Button","Loader2","RefreshCcw","Label","Input","e","DataTable","EmptyState","iso","d","now"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"subtasks-Bzh3o3EF.js","sources":["../../node_modules/lucide-react/dist/esm/icons/list-tree.js","../../src/hooks/use-subtasks.ts","../../src/routes/tasks/subtasks.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ListTree = createLucideIcon(\"ListTree\", [\n [\"path\", { d: \"M21 12h-8\", key: \"1bmf0i\" }],\n [\"path\", { d: \"M21 6H8\", key: \"1pqkrb\" }],\n [\"path\", { d: \"M21 18h-8\", key: \"1tm79t\" }],\n [\"path\", { d: \"M3 6v4c0 1.1.9 2 2 2h3\", key: \"1ywdgy\" }],\n [\"path\", { d: \"M3 10v6c0 1.1.9 2 2 2h3\", key: \"2wc746\" }]\n]);\n\nexport { ListTree as default };\n//# sourceMappingURL=list-tree.js.map\n","/**\n * useSubtasks — react-query wrapper for /api/subtasks.\n *\n * Subtasks are a flattened view of session.subtasks across every\n * conversation file in ~/.agim/sessions/. The endpoint is read-only\n * — no cancel / re-run mutation surface (yet). Live refresh rides on\n * the same SSE 'job' event (subtask state changes piggy-back on the\n * parent job's lifecycle).\n */\n\nimport { useQueryClient, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { ListSubtasksQuery, ListSubtasksResponse } from '@/types/api'\n\nexport const subtasksKeys = {\n all: ['subtasks'] as const,\n list: (q: ListSubtasksQuery) => ['subtasks', 'list', q] as const,\n}\n\nexport function useSubtasks(query: ListSubtasksQuery) {\n return useQuery<ListSubtasksResponse>({\n queryKey: subtasksKeys.list(query),\n queryFn: () => api.listSubtasks(query),\n })\n}\n\nexport function useInvalidateSubtasks() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: subtasksKeys.all })\n}\n","/**\n * /tasks/subtasks — flattened view of per-conversation child tasks\n * spawned by parent agents.\n *\n * Read-only: the backend doesn't expose cancel / re-run for subtasks\n * separately from the parent session. The page mirrors the columns\n * of /tasks/jobs but adds parent context (agent + platform) and\n * drops the duration / cost columns (which session.subtasks doesn't\n * track per-subtask).\n *\n * SSE: subscribes to the same `job` event as /tasks/jobs — subtask\n * status changes piggy-back on the parent job lifecycle in the\n * backend's event-bus.\n */\n\nimport { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Loader2, ListTree, RefreshCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { useSubtasks, useInvalidateSubtasks } from '@/hooks/use-subtasks'\nimport { useEventStream, type SseStatus } from '@/hooks/use-event-stream'\nimport type { Subtask } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst LIVE_STATUS_CLASS: Record<SseStatus, string> = {\n connected: 'text-success',\n connecting: 'text-text-dim',\n reconnecting: 'text-warning',\n closed: 'text-text-muted',\n}\n\nexport default function SubtasksRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const invalidate = useInvalidateSubtasks()\n const agent = params.get('agent') ?? ''\n\n const { data, isLoading, isFetching, refetch } = useSubtasks(\n agent ? { agent } : {},\n )\n const subtasks = data?.subtasks ?? []\n\n const live = useEventStream({\n job: () => invalidate(),\n })\n\n function setAgentFilter(v: string): void {\n const next = new URLSearchParams(params)\n if (!v) next.delete('agent')\n else next.set('agent', v)\n setParams(next, { replace: true })\n }\n\n const columns: DataTableColumn<Subtask>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('subtasks.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'agent',\n header: t('subtasks.col.agent'),\n cell: (r) => <span className=\"font-medium\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'prompt',\n header: t('subtasks.col.prompt'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.prompt}</span>,\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('subtasks.col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`subtasks.status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-32',\n },\n {\n id: 'parent',\n header: t('subtasks.col.parent'),\n cell: (r) => (\n <span className=\"text-text-dim\">\n <span className=\"font-medium text-text\">{r.parentAgent}</span>\n <span className=\"text-text-muted\"> / </span>\n <span title={r.parentSessionId}>{r.parentSessionId.slice(0, 8)}</span>\n </span>\n ),\n headClassName: 'w-40',\n },\n {\n id: 'platform',\n header: t('subtasks.col.platform'),\n cell: (r) => <span className=\"text-text-dim\">{r.platform}</span>,\n headClassName: 'w-28',\n hideOnMobile: true,\n },\n {\n id: 'createdAt',\n header: t('subtasks.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.createdAt)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('subtasks.title')}</h1>\n <span className={cn('text-xs font-medium tabular-nums', LIVE_STATUS_CLASS[live])}>\n {t(`jobs.live.${live}`)}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('subtasks.subtitle')}</p>\n </header>\n\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"agent-filter\" className=\"text-xs text-text-dim\">\n {t('subtasks.filter.agent')}\n </Label>\n <Input\n id=\"agent-filter\"\n value={agent}\n onChange={(e) => setAgentFilter(e.target.value)}\n placeholder={t('subtasks.filter.agentAny')}\n className=\"w-48\"\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n rows={subtasks}\n getRowId={(r) => `${r.parentSessionId}:${r.id}`}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<ListTree />}\n title={t('subtasks.empty.title')}\n description={t('subtasks.empty.description')}\n />\n }\n />\n </div>\n )\n}\n\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const now = new Date()\n const sameDay = d.toDateString() === now.toDateString()\n if (sameDay) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit' })\n }\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["ListTree","createLucideIcon","subtasksKeys","q","useSubtasks","query","useQuery","api","useInvalidateSubtasks","qc","useQueryClient","LIVE_STATUS_CLASS","SubtasksRoute","t","useTranslation","params","setParams","useSearchParams","invalidate","agent","data","isLoading","isFetching","refetch","subtasks","live","useEventStream","setAgentFilter","v","next","columns","useMemo","r","jsxs","jsx","StatusBadge","formatTime","cn","Button","Loader2","RefreshCcw","Label","Input","e","DataTable","EmptyState","iso","d","now"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,2 +1,2 @@
1
- import{j as s,c as t}from"./index-O0BQoyzo.js";import{r as o}from"./react-Cb2sDjhD.js";const l=o.forwardRef(({className:e,...a},r)=>s.jsx("div",{className:"w-full overflow-x-auto",children:s.jsx("table",{ref:r,className:t("w-full caption-bottom text-sm",e),...a})}));l.displayName="Table";const d=o.forwardRef(({className:e,...a},r)=>s.jsx("thead",{ref:r,className:t("[&_tr]:border-b [&_tr]:border-border bg-surface-2",e),...a}));d.displayName="TableHeader";const b=o.forwardRef(({className:e,...a},r)=>s.jsx("tbody",{ref:r,className:t("[&_tr:last-child]:border-0",e),...a}));b.displayName="TableBody";const c=o.forwardRef(({className:e,...a},r)=>s.jsx("tfoot",{ref:r,className:t("border-t border-border bg-surface-2 font-medium [&>tr]:last:border-b-0",e),...a}));c.displayName="TableFooter";const m=o.forwardRef(({className:e,...a},r)=>s.jsx("tr",{ref:r,className:t("border-b border-border transition-colors","hover:bg-surface-hover data-[state=selected]:bg-accent-bg",e),...a}));m.displayName="TableRow";const i=o.forwardRef(({className:e,...a},r)=>s.jsx("th",{ref:r,className:t("h-10 px-4 text-left align-middle","text-xs font-semibold uppercase tracking-wide text-text-dim","[&:has([role=checkbox])]:pr-0",e),...a}));i.displayName="TableHead";const f=o.forwardRef(({className:e,...a},r)=>s.jsx("td",{ref:r,className:t("p-3 align-middle [&:has([role=checkbox])]:pr-0",e),...a}));f.displayName="TableCell";const x=o.forwardRef(({className:e,...a},r)=>s.jsx("caption",{ref:r,className:t("mt-4 text-sm text-text-dim",e),...a}));x.displayName="TableCaption";export{l as T,d as a,m as b,i as c,b as d,f as e};
2
- //# sourceMappingURL=table-CPn1MRcy.js.map
1
+ import{j as s,c as t}from"./index-DEWFfW_Z.js";import{r as o}from"./react-DlP5eolq.js";const l=o.forwardRef(({className:e,...a},r)=>s.jsx("div",{className:"w-full overflow-x-auto",children:s.jsx("table",{ref:r,className:t("w-full caption-bottom text-sm",e),...a})}));l.displayName="Table";const d=o.forwardRef(({className:e,...a},r)=>s.jsx("thead",{ref:r,className:t("[&_tr]:border-b [&_tr]:border-border bg-surface-2",e),...a}));d.displayName="TableHeader";const b=o.forwardRef(({className:e,...a},r)=>s.jsx("tbody",{ref:r,className:t("[&_tr:last-child]:border-0",e),...a}));b.displayName="TableBody";const c=o.forwardRef(({className:e,...a},r)=>s.jsx("tfoot",{ref:r,className:t("border-t border-border bg-surface-2 font-medium [&>tr]:last:border-b-0",e),...a}));c.displayName="TableFooter";const m=o.forwardRef(({className:e,...a},r)=>s.jsx("tr",{ref:r,className:t("border-b border-border transition-colors","hover:bg-surface-hover data-[state=selected]:bg-accent-bg",e),...a}));m.displayName="TableRow";const i=o.forwardRef(({className:e,...a},r)=>s.jsx("th",{ref:r,className:t("h-10 px-4 text-left align-middle","text-xs font-semibold uppercase tracking-wide text-text-dim","[&:has([role=checkbox])]:pr-0",e),...a}));i.displayName="TableHead";const f=o.forwardRef(({className:e,...a},r)=>s.jsx("td",{ref:r,className:t("p-3 align-middle [&:has([role=checkbox])]:pr-0",e),...a}));f.displayName="TableCell";const x=o.forwardRef(({className:e,...a},r)=>s.jsx("caption",{ref:r,className:t("mt-4 text-sm text-text-dim",e),...a}));x.displayName="TableCaption";export{l as T,d as a,m as b,i as c,b as d,f as e};
2
+ //# sourceMappingURL=table-BbAOSyc8.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"table-CPn1MRcy.js","sources":["../../src/components/ui/table.tsx"],"sourcesContent":["/**\n * Table — accessible HTML table primitives. No 3rd-party dep; the\n * sortable / paginated / virtualised DataTable that wraps this lives\n * at components/common/data-table.tsx (PR-8).\n *\n * Mobile fallback strategy: the DataTable wrapper detects `< md` and\n * renders cards instead of rows. The primitives here keep a `min-w`\n * + overflow-x-auto wrapper as the fallback fallback (degrade to\n * horizontal scroll) so even raw `<Table>` usage is usable on phone.\n */\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nconst Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(\n ({ className, ...props }, ref) => (\n <div className=\"w-full overflow-x-auto\">\n <table\n ref={ref}\n className={cn('w-full caption-bottom text-sm', className)}\n {...props}\n />\n </div>\n ),\n)\nTable.displayName = 'Table'\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <thead ref={ref} className={cn('[&_tr]:border-b [&_tr]:border-border bg-surface-2', className)} {...props} />\n ),\n)\nTableHeader.displayName = 'TableHeader'\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />\n ),\n)\nTableBody.displayName = 'TableBody'\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n 'border-t border-border bg-surface-2 font-medium [&>tr]:last:border-b-0',\n className,\n )}\n {...props}\n />\n ),\n)\nTableFooter.displayName = 'TableFooter'\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(\n ({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n 'border-b border-border transition-colors',\n 'hover:bg-surface-hover data-[state=selected]:bg-accent-bg',\n className,\n )}\n {...props}\n />\n ),\n)\nTableRow.displayName = 'TableRow'\n\nconst TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n 'h-10 px-4 text-left align-middle',\n 'text-xs font-semibold uppercase tracking-wide text-text-dim',\n '[&:has([role=checkbox])]:pr-0',\n className,\n )}\n {...props}\n />\n ),\n)\nTableHead.displayName = 'TableHead'\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn('p-3 align-middle [&:has([role=checkbox])]:pr-0', className)}\n {...props}\n />\n ),\n)\nTableCell.displayName = 'TableCell'\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(\n ({ className, ...props }, ref) => (\n <caption ref={ref} className={cn('mt-4 text-sm text-text-dim', className)} {...props} />\n ),\n)\nTableCaption.displayName = 'TableCaption'\n\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }\n"],"names":["Table","React.forwardRef","className","props","ref","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","TableHead","TableCell","TableCaption"],"mappings":"uFAcA,MAAMA,EAAQC,EAAAA,WACZ,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,MAAC,MAAA,CAAI,UAAU,yBACb,SAAAA,EAAAA,IAAC,QAAA,CACC,IAAAD,EACA,UAAWE,EAAG,gCAAiCJ,CAAS,EACvD,GAAGC,CAAA,CAAA,CACN,CACF,CAEJ,EACAH,EAAM,YAAc,QAEpB,MAAMO,EAAcN,EAAAA,WAClB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,QAAA,CAAM,IAAAD,EAAU,UAAWE,EAAG,oDAAqDJ,CAAS,EAAI,GAAGC,CAAA,CAAO,CAE/G,EACAI,EAAY,YAAc,cAE1B,MAAMC,EAAYP,EAAAA,WAChB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,QAAA,CAAM,IAAAD,EAAU,UAAWE,EAAG,6BAA8BJ,CAAS,EAAI,GAAGC,CAAA,CAAO,CAExF,EACAK,EAAU,YAAc,YAExB,MAAMC,EAAcR,EAAAA,WAClB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,QAAA,CACC,IAAAD,EACA,UAAWE,EACT,yEACAJ,CAAA,EAED,GAAGC,CAAA,CAAA,CAGV,EACAM,EAAY,YAAc,cAE1B,MAAMC,EAAWT,EAAAA,WACf,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,KAAA,CACC,IAAAD,EACA,UAAWE,EACT,2CACA,4DACAJ,CAAA,EAED,GAAGC,CAAA,CAAA,CAGV,EACAO,EAAS,YAAc,WAEvB,MAAMC,EAAYV,EAAAA,WAChB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,KAAA,CACC,IAAAD,EACA,UAAWE,EACT,mCACA,8DACA,gCACAJ,CAAA,EAED,GAAGC,CAAA,CAAA,CAGV,EACAQ,EAAU,YAAc,YAExB,MAAMC,EAAYX,EAAAA,WAChB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,KAAA,CACC,IAAAD,EACA,UAAWE,EAAG,iDAAkDJ,CAAS,EACxE,GAAGC,CAAA,CAAA,CAGV,EACAS,EAAU,YAAc,YAExB,MAAMC,EAAeZ,EAAAA,WACnB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,UAAA,CAAQ,IAAAD,EAAU,UAAWE,EAAG,6BAA8BJ,CAAS,EAAI,GAAGC,CAAA,CAAO,CAE1F,EACAU,EAAa,YAAc"}
1
+ {"version":3,"file":"table-BbAOSyc8.js","sources":["../../src/components/ui/table.tsx"],"sourcesContent":["/**\n * Table — accessible HTML table primitives. No 3rd-party dep; the\n * sortable / paginated / virtualised DataTable that wraps this lives\n * at components/common/data-table.tsx (PR-8).\n *\n * Mobile fallback strategy: the DataTable wrapper detects `< md` and\n * renders cards instead of rows. The primitives here keep a `min-w`\n * + overflow-x-auto wrapper as the fallback fallback (degrade to\n * horizontal scroll) so even raw `<Table>` usage is usable on phone.\n */\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nconst Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(\n ({ className, ...props }, ref) => (\n <div className=\"w-full overflow-x-auto\">\n <table\n ref={ref}\n className={cn('w-full caption-bottom text-sm', className)}\n {...props}\n />\n </div>\n ),\n)\nTable.displayName = 'Table'\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <thead ref={ref} className={cn('[&_tr]:border-b [&_tr]:border-border bg-surface-2', className)} {...props} />\n ),\n)\nTableHeader.displayName = 'TableHeader'\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />\n ),\n)\nTableBody.displayName = 'TableBody'\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n 'border-t border-border bg-surface-2 font-medium [&>tr]:last:border-b-0',\n className,\n )}\n {...props}\n />\n ),\n)\nTableFooter.displayName = 'TableFooter'\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(\n ({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n 'border-b border-border transition-colors',\n 'hover:bg-surface-hover data-[state=selected]:bg-accent-bg',\n className,\n )}\n {...props}\n />\n ),\n)\nTableRow.displayName = 'TableRow'\n\nconst TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n 'h-10 px-4 text-left align-middle',\n 'text-xs font-semibold uppercase tracking-wide text-text-dim',\n '[&:has([role=checkbox])]:pr-0',\n className,\n )}\n {...props}\n />\n ),\n)\nTableHead.displayName = 'TableHead'\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn('p-3 align-middle [&:has([role=checkbox])]:pr-0', className)}\n {...props}\n />\n ),\n)\nTableCell.displayName = 'TableCell'\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(\n ({ className, ...props }, ref) => (\n <caption ref={ref} className={cn('mt-4 text-sm text-text-dim', className)} {...props} />\n ),\n)\nTableCaption.displayName = 'TableCaption'\n\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }\n"],"names":["Table","React.forwardRef","className","props","ref","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","TableHead","TableCell","TableCaption"],"mappings":"uFAcA,MAAMA,EAAQC,EAAAA,WACZ,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,MAAC,MAAA,CAAI,UAAU,yBACb,SAAAA,EAAAA,IAAC,QAAA,CACC,IAAAD,EACA,UAAWE,EAAG,gCAAiCJ,CAAS,EACvD,GAAGC,CAAA,CAAA,CACN,CACF,CAEJ,EACAH,EAAM,YAAc,QAEpB,MAAMO,EAAcN,EAAAA,WAClB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,QAAA,CAAM,IAAAD,EAAU,UAAWE,EAAG,oDAAqDJ,CAAS,EAAI,GAAGC,CAAA,CAAO,CAE/G,EACAI,EAAY,YAAc,cAE1B,MAAMC,EAAYP,EAAAA,WAChB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,QAAA,CAAM,IAAAD,EAAU,UAAWE,EAAG,6BAA8BJ,CAAS,EAAI,GAAGC,CAAA,CAAO,CAExF,EACAK,EAAU,YAAc,YAExB,MAAMC,EAAcR,EAAAA,WAClB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,QAAA,CACC,IAAAD,EACA,UAAWE,EACT,yEACAJ,CAAA,EAED,GAAGC,CAAA,CAAA,CAGV,EACAM,EAAY,YAAc,cAE1B,MAAMC,EAAWT,EAAAA,WACf,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,KAAA,CACC,IAAAD,EACA,UAAWE,EACT,2CACA,4DACAJ,CAAA,EAED,GAAGC,CAAA,CAAA,CAGV,EACAO,EAAS,YAAc,WAEvB,MAAMC,EAAYV,EAAAA,WAChB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,KAAA,CACC,IAAAD,EACA,UAAWE,EACT,mCACA,8DACA,gCACAJ,CAAA,EAED,GAAGC,CAAA,CAAA,CAGV,EACAQ,EAAU,YAAc,YAExB,MAAMC,EAAYX,EAAAA,WAChB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,KAAA,CACC,IAAAD,EACA,UAAWE,EAAG,iDAAkDJ,CAAS,EACxE,GAAGC,CAAA,CAAA,CAGV,EACAS,EAAU,YAAc,YAExB,MAAMC,EAAeZ,EAAAA,WACnB,CAAC,CAAE,UAAAC,EAAW,GAAGC,CAAA,EAASC,IACxBC,EAAAA,IAAC,UAAA,CAAQ,IAAAD,EAAU,UAAWE,EAAG,6BAA8BJ,CAAS,EAAI,GAAGC,CAAA,CAAO,CAE1F,EACAU,EAAa,YAAc"}
@@ -1,7 +1,7 @@
1
- import{n as S,u as w,e as M,j as e,B as L,L as p,S as j,f as u,g as f,h as N,i as b}from"./index-O0BQoyzo.js";import{E as R}from"./empty-state-C-qjOHyu.js";import{T as V,a as $,b as g,c as l,d as E,e as c}from"./table-CPn1MRcy.js";import{a as F}from"./use-observability-C2M6WZ9W.js";import{L as I}from"./loader-circle-9VUMGitw.js";import{R as P}from"./refresh-ccw-D2CWiyU_.js";import"./react-Cb2sDjhD.js";import"./useQuery-PdiC7-sY.js";/**
1
+ import{n as S,u as w,e as M,j as e,B as L,L as p,S as j,f as u,g as f,h as N,i as b}from"./index-DEWFfW_Z.js";import{E as R}from"./empty-state-D9Hi0Atm.js";import{T as V,a as $,b as g,c as l,d as E,e as c}from"./table-BbAOSyc8.js";import{a as F}from"./use-observability-Coj02yDo.js";import{L as I}from"./loader-circle-Bbw4pEyE.js";import{R as P}from"./refresh-ccw-uNKeBeRl.js";import"./react-DlP5eolq.js";import"./useQuery-CY2iazjN.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const B=S("ChartColumn",[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]]),z=["user","agent","platform","intent"],H=["cost","calls","errors","avg_latency"];function K(){const{t:a}=w(["observability","common"]),[n,y]=M(),v=Math.max(1,Number(n.get("days"))||7),i=n.get("dim")??"agent",r=n.get("by")??"cost";function m(s){const t=new URLSearchParams(n);for(const[x,h]of Object.entries(s))h==null?t.delete(x):t.set(x,h);y(t,{replace:!0})}const{data:C,isLoading:T,isFetching:o,refetch:k}=F({dim:i,by:r,days:v,limit:20}),d=C?.items??[];return e.jsxs("div",{className:"mx-auto flex max-w-7xl flex-col gap-4",children:[e.jsx("header",{className:"flex flex-col gap-1",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:a("topn.title")}),e.jsxs(L,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>k(),disabled:o,"aria-label":a("actions.refresh",{ns:"common"}),children:[o?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(P,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("actions.refresh",{ns:"common"})})]})]})}),e.jsxs("div",{className:"flex flex-wrap items-end gap-2",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(p,{htmlFor:"dim",className:"text-xs text-text-dim",children:a("topn.filter.dim")}),e.jsxs(j,{value:i,onValueChange:s=>m({dim:s==="agent"?null:s}),children:[e.jsx(u,{id:"dim",className:"w-32",children:e.jsx(f,{})}),e.jsx(N,{children:z.map(s=>e.jsx(b,{value:s,children:a(`topn.dim.${s}`)},s))})]})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(p,{htmlFor:"by",className:"text-xs text-text-dim",children:a("topn.filter.metric")}),e.jsxs(j,{value:r,onValueChange:s=>m({by:s==="cost"?null:s}),children:[e.jsx(u,{id:"by",className:"w-36",children:e.jsx(f,{})}),e.jsx(N,{children:H.map(s=>e.jsx(b,{value:s,children:a(`topn.metric.${s}`)},s))})]})]})]}),T?e.jsx("div",{className:"h-48 w-full rounded-md bg-surface-2 animate-pulse"}):d.length===0?e.jsx(R,{icon:e.jsx(B,{}),title:a("topn.empty.title"),description:a("topn.empty.description")}):e.jsxs(V,{children:[e.jsx($,{children:e.jsxs(g,{children:[e.jsx(l,{className:"w-12",children:a("topn.col.rank")}),e.jsx(l,{children:a("topn.col.key")}),e.jsx(l,{className:"w-24",children:a("topn.col.calls")}),e.jsx(l,{className:"w-24",children:a("topn.col.cost")}),e.jsx(l,{className:"w-24",children:a("topn.col.errors")}),e.jsx(l,{className:"w-32",children:a("topn.col.avgLatencyMs")})]})}),e.jsx(E,{children:d.map((s,t)=>e.jsxs(g,{children:[e.jsx(c,{className:"tabular-nums text-text-dim",children:t+1}),e.jsx(c,{className:"font-medium",children:s.key}),e.jsx(c,{className:"tabular-nums",children:s.calls}),e.jsxs(c,{className:"tabular-nums",children:["$",s.cost.toFixed(4)]}),e.jsx(c,{className:"tabular-nums",children:e.jsx("span",{className:s.errors>0?"text-danger":"text-text-dim",children:s.errors})}),e.jsxs(c,{className:"tabular-nums",children:[Math.round(s.avgLatencyMs),"ms"]})]},`${s.key}-${t}`))})]})]})}export{K as default};
7
- //# sourceMappingURL=topn-Ba3RjcK1.js.map
7
+ //# sourceMappingURL=topn-DkhYw-Gp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"topn-Ba3RjcK1.js","sources":["../../node_modules/lucide-react/dist/esm/icons/chart-column.js","../../src/routes/observability/topn.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartColumn = createLucideIcon(\"ChartColumn\", [\n [\"path\", { d: \"M3 3v16a2 2 0 0 0 2 2h16\", key: \"c24i48\" }],\n [\"path\", { d: \"M18 17V9\", key: \"2bz60n\" }],\n [\"path\", { d: \"M13 17V5\", key: \"1frdt8\" }],\n [\"path\", { d: \"M8 17v-3\", key: \"17ska0\" }]\n]);\n\nexport { ChartColumn as default };\n//# sourceMappingURL=chart-column.js.map\n","/**\n * /observability/topn — leaderboard grouped by a dimension, sorted\n * by a metric. Dim + metric live in URL state alongside the\n * layout's ?days= so the URL fully describes the view.\n */\n\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { BarChart3, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { EmptyState } from '@/components/common/empty-state'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table'\nimport { Button } from '@/components/ui/button'\nimport { Label } from '@/components/ui/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useTopN } from '@/hooks/use-observability'\nimport type { TopNDim, TopNMetric } from '@/types/api'\n\nconst DIMS: TopNDim[] = ['user', 'agent', 'platform', 'intent']\nconst METRICS: TopNMetric[] = ['cost', 'calls', 'errors', 'avg_latency']\n\nexport default function ObservabilityTopNRoute(): JSX.Element {\n const { t } = useTranslation(['observability', 'common'])\n const [params, setParams] = useSearchParams()\n const days = Math.max(1, Number(params.get('days')) || 7)\n const dim = (params.get('dim') as TopNDim | null) ?? 'agent'\n const by = (params.get('by') as TopNMetric | null) ?? 'cost'\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null) next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: true })\n }\n\n const { data, isLoading, isFetching, refetch } = useTopN({ dim, by, days, limit: 20 })\n const items = data?.items ?? []\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('topn.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n </header>\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"dim\" className=\"text-xs text-text-dim\">{t('topn.filter.dim')}</Label>\n <Select value={dim} onValueChange={(v) => patchParams({ dim: v === 'agent' ? null : v })}>\n <SelectTrigger id=\"dim\" className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {DIMS.map((d) => (\n <SelectItem key={d} value={d}>{t(`topn.dim.${d}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"by\" className=\"text-xs text-text-dim\">{t('topn.filter.metric')}</Label>\n <Select value={by} onValueChange={(v) => patchParams({ by: v === 'cost' ? null : v })}>\n <SelectTrigger id=\"by\" className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {METRICS.map((m) => (\n <SelectItem key={m} value={m}>{t(`topn.metric.${m}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {isLoading ? (\n <div className=\"h-48 w-full rounded-md bg-surface-2 animate-pulse\" />\n ) : items.length === 0 ? (\n <EmptyState\n icon={<BarChart3 />}\n title={t('topn.empty.title')}\n description={t('topn.empty.description')}\n />\n ) : (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-12\">{t('topn.col.rank')}</TableHead>\n <TableHead>{t('topn.col.key')}</TableHead>\n <TableHead className=\"w-24\">{t('topn.col.calls')}</TableHead>\n <TableHead className=\"w-24\">{t('topn.col.cost')}</TableHead>\n <TableHead className=\"w-24\">{t('topn.col.errors')}</TableHead>\n <TableHead className=\"w-32\">{t('topn.col.avgLatencyMs')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {items.map((row, i) => (\n <TableRow key={`${row.key}-${i}`}>\n <TableCell className=\"tabular-nums text-text-dim\">{i + 1}</TableCell>\n <TableCell className=\"font-medium\">{row.key}</TableCell>\n <TableCell className=\"tabular-nums\">{row.calls}</TableCell>\n <TableCell className=\"tabular-nums\">${row.cost.toFixed(4)}</TableCell>\n <TableCell className=\"tabular-nums\">\n <span className={row.errors > 0 ? 'text-danger' : 'text-text-dim'}>{row.errors}</span>\n </TableCell>\n <TableCell className=\"tabular-nums\">{Math.round(row.avgLatencyMs)}ms</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </div>\n )\n}\n"],"names":["ChartColumn","createLucideIcon","DIMS","METRICS","ObservabilityTopNRoute","t","useTranslation","params","setParams","useSearchParams","days","dim","by","patchParams","patch","next","k","v","data","isLoading","isFetching","refetch","useTopN","items","jsxs","jsx","Button","Loader2","RefreshCcw","Label","Select","SelectTrigger","SelectValue","SelectContent","d","SelectItem","m","EmptyState","BarChart3","Table","TableHeader","TableRow","TableHead","TableBody","row","i","TableCell"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"topn-DkhYw-Gp.js","sources":["../../node_modules/lucide-react/dist/esm/icons/chart-column.js","../../src/routes/observability/topn.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartColumn = createLucideIcon(\"ChartColumn\", [\n [\"path\", { d: \"M3 3v16a2 2 0 0 0 2 2h16\", key: \"c24i48\" }],\n [\"path\", { d: \"M18 17V9\", key: \"2bz60n\" }],\n [\"path\", { d: \"M13 17V5\", key: \"1frdt8\" }],\n [\"path\", { d: \"M8 17v-3\", key: \"17ska0\" }]\n]);\n\nexport { ChartColumn as default };\n//# sourceMappingURL=chart-column.js.map\n","/**\n * /observability/topn — leaderboard grouped by a dimension, sorted\n * by a metric. Dim + metric live in URL state alongside the\n * layout's ?days= so the URL fully describes the view.\n */\n\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { BarChart3, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { EmptyState } from '@/components/common/empty-state'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table'\nimport { Button } from '@/components/ui/button'\nimport { Label } from '@/components/ui/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useTopN } from '@/hooks/use-observability'\nimport type { TopNDim, TopNMetric } from '@/types/api'\n\nconst DIMS: TopNDim[] = ['user', 'agent', 'platform', 'intent']\nconst METRICS: TopNMetric[] = ['cost', 'calls', 'errors', 'avg_latency']\n\nexport default function ObservabilityTopNRoute(): JSX.Element {\n const { t } = useTranslation(['observability', 'common'])\n const [params, setParams] = useSearchParams()\n const days = Math.max(1, Number(params.get('days')) || 7)\n const dim = (params.get('dim') as TopNDim | null) ?? 'agent'\n const by = (params.get('by') as TopNMetric | null) ?? 'cost'\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null) next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: true })\n }\n\n const { data, isLoading, isFetching, refetch } = useTopN({ dim, by, days, limit: 20 })\n const items = data?.items ?? []\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('topn.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n </header>\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"dim\" className=\"text-xs text-text-dim\">{t('topn.filter.dim')}</Label>\n <Select value={dim} onValueChange={(v) => patchParams({ dim: v === 'agent' ? null : v })}>\n <SelectTrigger id=\"dim\" className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {DIMS.map((d) => (\n <SelectItem key={d} value={d}>{t(`topn.dim.${d}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"by\" className=\"text-xs text-text-dim\">{t('topn.filter.metric')}</Label>\n <Select value={by} onValueChange={(v) => patchParams({ by: v === 'cost' ? null : v })}>\n <SelectTrigger id=\"by\" className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {METRICS.map((m) => (\n <SelectItem key={m} value={m}>{t(`topn.metric.${m}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {isLoading ? (\n <div className=\"h-48 w-full rounded-md bg-surface-2 animate-pulse\" />\n ) : items.length === 0 ? (\n <EmptyState\n icon={<BarChart3 />}\n title={t('topn.empty.title')}\n description={t('topn.empty.description')}\n />\n ) : (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-12\">{t('topn.col.rank')}</TableHead>\n <TableHead>{t('topn.col.key')}</TableHead>\n <TableHead className=\"w-24\">{t('topn.col.calls')}</TableHead>\n <TableHead className=\"w-24\">{t('topn.col.cost')}</TableHead>\n <TableHead className=\"w-24\">{t('topn.col.errors')}</TableHead>\n <TableHead className=\"w-32\">{t('topn.col.avgLatencyMs')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {items.map((row, i) => (\n <TableRow key={`${row.key}-${i}`}>\n <TableCell className=\"tabular-nums text-text-dim\">{i + 1}</TableCell>\n <TableCell className=\"font-medium\">{row.key}</TableCell>\n <TableCell className=\"tabular-nums\">{row.calls}</TableCell>\n <TableCell className=\"tabular-nums\">${row.cost.toFixed(4)}</TableCell>\n <TableCell className=\"tabular-nums\">\n <span className={row.errors > 0 ? 'text-danger' : 'text-text-dim'}>{row.errors}</span>\n </TableCell>\n <TableCell className=\"tabular-nums\">{Math.round(row.avgLatencyMs)}ms</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </div>\n )\n}\n"],"names":["ChartColumn","createLucideIcon","DIMS","METRICS","ObservabilityTopNRoute","t","useTranslation","params","setParams","useSearchParams","days","dim","by","patchParams","patch","next","k","v","data","isLoading","isFetching","refetch","useTopN","items","jsxs","jsx","Button","Loader2","RefreshCcw","Label","Select","SelectTrigger","SelectValue","SelectContent","d","SelectItem","m","EmptyState","BarChart3","Table","TableHeader","TableRow","TableHead","TableBody","row","i","TableCell"],"mappings":"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","x_google_ignoreList":[0]}