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.
- package/CHANGELOG.md +159 -0
- package/dist/cli-ui/setup-llm.d.ts.map +1 -1
- package/dist/cli-ui/setup-llm.js +3 -1
- package/dist/cli-ui/setup-llm.js.map +1 -1
- package/dist/core/circuit-breaker.d.ts +28 -0
- package/dist/core/circuit-breaker.d.ts.map +1 -1
- package/dist/core/circuit-breaker.js +45 -0
- package/dist/core/circuit-breaker.js.map +1 -1
- package/dist/core/intent.d.ts.map +1 -1
- package/dist/core/intent.js +3 -1
- package/dist/core/intent.js.map +1 -1
- package/dist/core/llm/agent-loop.d.ts +9 -1
- package/dist/core/llm/agent-loop.d.ts.map +1 -1
- package/dist/core/llm/agent-loop.js +80 -1
- package/dist/core/llm/agent-loop.js.map +1 -1
- package/dist/core/llm/anthropic-provider.d.ts.map +1 -1
- package/dist/core/llm/anthropic-provider.js +18 -4
- package/dist/core/llm/anthropic-provider.js.map +1 -1
- package/dist/core/llm/hallucination-detector.d.ts +33 -0
- package/dist/core/llm/hallucination-detector.d.ts.map +1 -0
- package/dist/core/llm/hallucination-detector.js +103 -0
- package/dist/core/llm/hallucination-detector.js.map +1 -0
- package/dist/core/llm/imhub-dispatcher.d.ts.map +1 -1
- package/dist/core/llm/imhub-dispatcher.js +7 -0
- package/dist/core/llm/imhub-dispatcher.js.map +1 -1
- package/dist/core/llm/provider-base.d.ts +9 -0
- package/dist/core/llm/provider-base.d.ts.map +1 -1
- package/dist/core/llm/provider-base.js.map +1 -1
- package/dist/core/memory-distill.d.ts.map +1 -1
- package/dist/core/memory-distill.js +18 -3
- package/dist/core/memory-distill.js.map +1 -1
- package/dist/core/memory.d.ts +14 -0
- package/dist/core/memory.d.ts.map +1 -1
- package/dist/core/memory.js +39 -0
- package/dist/core/memory.js.map +1 -1
- package/dist/core/message-sink.d.ts +6 -0
- package/dist/core/message-sink.d.ts.map +1 -1
- package/dist/core/message-sink.js +18 -3
- package/dist/core/message-sink.js.map +1 -1
- package/dist/core/outbox.d.ts +30 -2
- package/dist/core/outbox.d.ts.map +1 -1
- package/dist/core/outbox.js +102 -10
- package/dist/core/outbox.js.map +1 -1
- package/dist/core/reminders.d.ts.map +1 -1
- package/dist/core/reminders.js +11 -1
- package/dist/core/reminders.js.map +1 -1
- package/dist/core/router.d.ts.map +1 -1
- package/dist/core/router.js +16 -4
- package/dist/core/router.js.map +1 -1
- package/dist/core/schedule.d.ts +18 -0
- package/dist/core/schedule.d.ts.map +1 -1
- package/dist/core/schedule.js +80 -17
- package/dist/core/schedule.js.map +1 -1
- package/dist/core/sensitive-paths.d.ts.map +1 -1
- package/dist/core/sensitive-paths.js +53 -9
- package/dist/core/sensitive-paths.js.map +1 -1
- package/dist/core/skills/builtin/ECC_LICENSE +21 -0
- package/dist/core/skills/builtin/ECC_NOTICE.md +22 -0
- package/dist/core/skills/builtin/accessibility/SKILL.md +146 -0
- package/dist/core/skills/builtin/agent-eval/SKILL.md +145 -0
- package/dist/core/skills/builtin/agent-harness-construction/SKILL.md +73 -0
- package/dist/core/skills/builtin/agent-introspection-debugging/SKILL.md +153 -0
- package/dist/core/skills/builtin/agentic-engineering/SKILL.md +63 -0
- package/dist/core/skills/builtin/ai-first-engineering/SKILL.md +51 -0
- package/dist/core/skills/builtin/ai-regression-testing/SKILL.md +385 -0
- package/dist/core/skills/builtin/android-clean-architecture/SKILL.md +339 -0
- package/dist/core/skills/builtin/angular-developer/SKILL.md +154 -0
- package/dist/core/skills/builtin/angular-developer/references/angular-animations.md +160 -0
- package/dist/core/skills/builtin/angular-developer/references/angular-aria.md +410 -0
- package/dist/core/skills/builtin/angular-developer/references/cli.md +86 -0
- package/dist/core/skills/builtin/angular-developer/references/component-harnesses.md +59 -0
- package/dist/core/skills/builtin/angular-developer/references/component-styling.md +91 -0
- package/dist/core/skills/builtin/angular-developer/references/components.md +117 -0
- package/dist/core/skills/builtin/angular-developer/references/creating-services.md +97 -0
- package/dist/core/skills/builtin/angular-developer/references/data-resolvers.md +69 -0
- package/dist/core/skills/builtin/angular-developer/references/define-routes.md +67 -0
- package/dist/core/skills/builtin/angular-developer/references/defining-providers.md +72 -0
- package/dist/core/skills/builtin/angular-developer/references/di-fundamentals.md +120 -0
- package/dist/core/skills/builtin/angular-developer/references/e2e-testing.md +56 -0
- package/dist/core/skills/builtin/angular-developer/references/effects.md +83 -0
- package/dist/core/skills/builtin/angular-developer/references/hierarchical-injectors.md +43 -0
- package/dist/core/skills/builtin/angular-developer/references/host-elements.md +80 -0
- package/dist/core/skills/builtin/angular-developer/references/injection-context.md +63 -0
- package/dist/core/skills/builtin/angular-developer/references/inputs.md +101 -0
- package/dist/core/skills/builtin/angular-developer/references/linked-signal.md +59 -0
- package/dist/core/skills/builtin/angular-developer/references/loading-strategies.md +61 -0
- package/dist/core/skills/builtin/angular-developer/references/mcp.md +108 -0
- package/dist/core/skills/builtin/angular-developer/references/navigate-to-routes.md +69 -0
- package/dist/core/skills/builtin/angular-developer/references/outputs.md +86 -0
- package/dist/core/skills/builtin/angular-developer/references/reactive-forms.md +122 -0
- package/dist/core/skills/builtin/angular-developer/references/rendering-strategies.md +44 -0
- package/dist/core/skills/builtin/angular-developer/references/resource.md +77 -0
- package/dist/core/skills/builtin/angular-developer/references/route-animations.md +56 -0
- package/dist/core/skills/builtin/angular-developer/references/route-guards.md +52 -0
- package/dist/core/skills/builtin/angular-developer/references/router-lifecycle.md +45 -0
- package/dist/core/skills/builtin/angular-developer/references/router-testing.md +87 -0
- package/dist/core/skills/builtin/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/dist/core/skills/builtin/angular-developer/references/signal-forms.md +795 -0
- package/dist/core/skills/builtin/angular-developer/references/signals-overview.md +94 -0
- package/dist/core/skills/builtin/angular-developer/references/tailwind-css.md +69 -0
- package/dist/core/skills/builtin/angular-developer/references/template-driven-forms.md +114 -0
- package/dist/core/skills/builtin/angular-developer/references/testing-fundamentals.md +65 -0
- package/dist/core/skills/builtin/api-connector-builder/SKILL.md +120 -0
- package/dist/core/skills/builtin/api-design/SKILL.md +523 -0
- package/dist/core/skills/builtin/architecture-decision-records/SKILL.md +179 -0
- package/dist/core/skills/builtin/article-writing/SKILL.md +79 -0
- package/dist/core/skills/builtin/automation-audit-ops/SKILL.md +142 -0
- package/dist/core/skills/builtin/autonomous-agent-harness/SKILL.md +273 -0
- package/dist/core/skills/builtin/autonomous-loops/SKILL.md +610 -0
- package/dist/core/skills/builtin/backend-patterns/SKILL.md +561 -0
- package/dist/core/skills/builtin/benchmark/SKILL.md +93 -0
- package/dist/core/skills/builtin/benchmark-optimization-loop/SKILL.md +69 -0
- package/dist/core/skills/builtin/blueprint/SKILL.md +105 -0
- package/dist/core/skills/builtin/browser-qa/SKILL.md +87 -0
- package/dist/core/skills/builtin/bun-runtime/SKILL.md +84 -0
- package/dist/core/skills/builtin/cisco-ios-patterns/SKILL.md +163 -0
- package/dist/core/skills/builtin/claude-devfleet/SKILL.md +111 -0
- package/dist/core/skills/builtin/click-path-audit/SKILL.md +244 -0
- package/dist/core/skills/builtin/clickhouse-io/SKILL.md +439 -0
- package/dist/core/skills/builtin/code-tour/SKILL.md +236 -0
- package/dist/core/skills/builtin/codebase-onboarding/SKILL.md +233 -0
- package/dist/core/skills/builtin/codehealth-mcp/SKILL.md +166 -0
- package/dist/core/skills/builtin/coding-standards/SKILL.md +550 -0
- package/dist/core/skills/builtin/compose-multiplatform-patterns/SKILL.md +299 -0
- package/dist/core/skills/builtin/config-gc/SKILL.md +119 -0
- package/dist/core/skills/builtin/content-hash-cache-pattern/SKILL.md +161 -0
- package/dist/core/skills/builtin/context-budget/SKILL.md +135 -0
- package/dist/core/skills/builtin/continuous-agent-loop/SKILL.md +45 -0
- package/dist/core/skills/builtin/continuous-learning/SKILL.md +131 -0
- package/dist/core/skills/builtin/continuous-learning/config.json +18 -0
- package/dist/core/skills/builtin/continuous-learning/evaluate-session.sh +69 -0
- package/dist/core/skills/builtin/continuous-learning-v2/SKILL.md +360 -0
- package/dist/core/skills/builtin/continuous-learning-v2/agents/observer-loop.sh +335 -0
- package/dist/core/skills/builtin/continuous-learning-v2/agents/observer.md +198 -0
- package/dist/core/skills/builtin/continuous-learning-v2/agents/session-guardian.sh +150 -0
- package/dist/core/skills/builtin/continuous-learning-v2/agents/start-observer.sh +248 -0
- package/dist/core/skills/builtin/continuous-learning-v2/config.json +8 -0
- package/dist/core/skills/builtin/continuous-learning-v2/hooks/observe.sh +498 -0
- package/dist/core/skills/builtin/continuous-learning-v2/scripts/detect-project.sh +322 -0
- package/dist/core/skills/builtin/continuous-learning-v2/scripts/instinct-cli.py +1914 -0
- package/dist/core/skills/builtin/continuous-learning-v2/scripts/lib/homunculus-dir.sh +31 -0
- package/dist/core/skills/builtin/continuous-learning-v2/scripts/migrate-homunculus.sh +62 -0
- package/dist/core/skills/builtin/continuous-learning-v2/scripts/test_parse_instinct.py +1045 -0
- package/dist/core/skills/builtin/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/dist/core/skills/builtin/cost-tracking/SKILL.md +147 -0
- package/dist/core/skills/builtin/council/SKILL.md +203 -0
- package/dist/core/skills/builtin/cpp-coding-standards/SKILL.md +723 -0
- package/dist/core/skills/builtin/cpp-testing/SKILL.md +324 -0
- package/dist/core/skills/builtin/crosspost/SKILL.md +111 -0
- package/dist/core/skills/builtin/csharp-testing/SKILL.md +321 -0
- package/dist/core/skills/builtin/customs-trade-compliance/SKILL.md +263 -0
- package/dist/core/skills/builtin/dart-flutter-patterns/SKILL.md +563 -0
- package/dist/core/skills/builtin/dashboard-builder/SKILL.md +108 -0
- package/dist/core/skills/builtin/data-scraper-agent/SKILL.md +764 -0
- package/dist/core/skills/builtin/data-throughput-accelerator/SKILL.md +72 -0
- package/dist/core/skills/builtin/database-migrations/SKILL.md +429 -0
- package/dist/core/skills/builtin/deep-research/SKILL.md +159 -0
- package/dist/core/skills/builtin/defi-amm-security/SKILL.md +166 -0
- package/dist/core/skills/builtin/deployment-patterns/SKILL.md +427 -0
- package/dist/core/skills/builtin/design-system/SKILL.md +82 -0
- package/dist/core/skills/builtin/django-celery/SKILL.md +457 -0
- package/dist/core/skills/builtin/django-patterns/SKILL.md +734 -0
- package/dist/core/skills/builtin/django-security/SKILL.md +593 -0
- package/dist/core/skills/builtin/django-tdd/SKILL.md +729 -0
- package/dist/core/skills/builtin/django-verification/SKILL.md +469 -0
- package/dist/core/skills/builtin/dmux-workflows/SKILL.md +191 -0
- package/dist/core/skills/builtin/docker-patterns/SKILL.md +364 -0
- package/dist/core/skills/builtin/documentation-lookup/SKILL.md +90 -0
- package/dist/core/skills/builtin/dotnet-patterns/SKILL.md +321 -0
- package/dist/core/skills/builtin/dynamic-workflow-mode/SKILL.md +123 -0
- package/dist/core/skills/builtin/e2e-testing/SKILL.md +326 -0
- package/dist/core/skills/builtin/email-ops/SKILL.md +121 -0
- package/dist/core/skills/builtin/energy-procurement/SKILL.md +228 -0
- package/dist/core/skills/builtin/enterprise-agent-ops/SKILL.md +50 -0
- package/dist/core/skills/builtin/error-handling/SKILL.md +376 -0
- package/dist/core/skills/builtin/eval-harness/SKILL.md +270 -0
- package/dist/core/skills/builtin/evm-token-decimals/SKILL.md +130 -0
- package/dist/core/skills/builtin/exa-search/SKILL.md +107 -0
- package/dist/core/skills/builtin/fal-ai-media/SKILL.md +288 -0
- package/dist/core/skills/builtin/fastapi-patterns/SKILL.md +513 -0
- package/dist/core/skills/builtin/finance-billing-ops/SKILL.md +127 -0
- package/dist/core/skills/builtin/flox-environments/SKILL.md +496 -0
- package/dist/core/skills/builtin/flutter-dart-code-review/SKILL.md +435 -0
- package/dist/core/skills/builtin/foundation-models-on-device/SKILL.md +243 -0
- package/dist/core/skills/builtin/frontend-a11y/SKILL.md +445 -0
- package/dist/core/skills/builtin/frontend-design-direction/SKILL.md +92 -0
- package/dist/core/skills/builtin/frontend-patterns/SKILL.md +656 -0
- package/dist/core/skills/builtin/frontend-slides/SKILL.md +184 -0
- package/dist/core/skills/builtin/frontend-slides/STYLE_PRESETS.md +330 -0
- package/dist/core/skills/builtin/frontend-slides/animation-patterns.md +122 -0
- package/dist/core/skills/builtin/frontend-slides/html-template.md +419 -0
- package/dist/core/skills/builtin/frontend-slides/scripts/export-pdf.sh +418 -0
- package/dist/core/skills/builtin/frontend-slides/scripts/extract-pptx.py +96 -0
- package/dist/core/skills/builtin/frontend-slides/viewport-base.css +153 -0
- package/dist/core/skills/builtin/fsharp-testing/SKILL.md +280 -0
- package/dist/core/skills/builtin/gan-style-harness/SKILL.md +278 -0
- package/dist/core/skills/builtin/gateguard/SKILL.md +132 -0
- package/dist/core/skills/builtin/git-workflow/SKILL.md +715 -0
- package/dist/core/skills/builtin/github-ops/SKILL.md +144 -0
- package/dist/core/skills/builtin/golang-patterns/SKILL.md +674 -0
- package/dist/core/skills/builtin/golang-testing/SKILL.md +720 -0
- package/dist/core/skills/builtin/healthcare-cdss-patterns/SKILL.md +245 -0
- package/dist/core/skills/builtin/healthcare-emr-patterns/SKILL.md +159 -0
- package/dist/core/skills/builtin/healthcare-eval-harness/SKILL.md +207 -0
- package/dist/core/skills/builtin/healthcare-phi-compliance/SKILL.md +145 -0
- package/dist/core/skills/builtin/hermes-imports/SKILL.md +88 -0
- package/dist/core/skills/builtin/hexagonal-architecture/SKILL.md +276 -0
- package/dist/core/skills/builtin/hipaa-compliance/SKILL.md +78 -0
- package/dist/core/skills/builtin/hookify-rules/SKILL.md +128 -0
- package/dist/core/skills/builtin/inherit-legacy-style/SKILL.md +156 -0
- package/dist/core/skills/builtin/intent-driven-development/SKILL.md +360 -0
- package/dist/core/skills/builtin/inventory-demand-planning/SKILL.md +247 -0
- package/dist/core/skills/builtin/ios-icon-gen/SKILL.md +157 -0
- package/dist/core/skills/builtin/ios-icon-gen/scripts/generate_icons.swift +258 -0
- package/dist/core/skills/builtin/ios-icon-gen/scripts/iconify_gen.sh +235 -0
- package/dist/core/skills/builtin/iterative-retrieval/SKILL.md +211 -0
- package/dist/core/skills/builtin/java-coding-standards/SKILL.md +383 -0
- package/dist/core/skills/builtin/jira-integration/SKILL.md +302 -0
- package/dist/core/skills/builtin/jpa-patterns/SKILL.md +151 -0
- package/dist/core/skills/builtin/knowledge-ops/SKILL.md +154 -0
- package/dist/core/skills/builtin/kotlin-coroutines-flows/SKILL.md +284 -0
- package/dist/core/skills/builtin/kotlin-exposed-patterns/SKILL.md +719 -0
- package/dist/core/skills/builtin/kotlin-ktor-patterns/SKILL.md +689 -0
- package/dist/core/skills/builtin/kotlin-patterns/SKILL.md +711 -0
- package/dist/core/skills/builtin/kotlin-testing/SKILL.md +824 -0
- package/dist/core/skills/builtin/kubernetes-patterns/SKILL.md +755 -0
- package/dist/core/skills/builtin/laravel-patterns/SKILL.md +415 -0
- package/dist/core/skills/builtin/laravel-plugin-discovery/SKILL.md +229 -0
- package/dist/core/skills/builtin/laravel-security/SKILL.md +947 -0
- package/dist/core/skills/builtin/laravel-tdd/SKILL.md +674 -0
- package/dist/core/skills/builtin/laravel-verification/SKILL.md +179 -0
- package/dist/core/skills/builtin/latency-critical-systems/SKILL.md +73 -0
- package/dist/core/skills/builtin/lead-intelligence/SKILL.md +321 -0
- package/dist/core/skills/builtin/lead-intelligence/agents/enrichment-agent.md +85 -0
- package/dist/core/skills/builtin/lead-intelligence/agents/mutual-mapper.md +75 -0
- package/dist/core/skills/builtin/lead-intelligence/agents/outreach-drafter.md +98 -0
- package/dist/core/skills/builtin/lead-intelligence/agents/signal-scorer.md +60 -0
- package/dist/core/skills/builtin/liquid-glass-design/SKILL.md +279 -0
- package/dist/core/skills/builtin/llm-trading-agent-security/SKILL.md +146 -0
- package/dist/core/skills/builtin/logistics-exception-management/SKILL.md +222 -0
- package/dist/core/skills/builtin/make-interfaces-feel-better/SKILL.md +151 -0
- package/dist/core/skills/builtin/market-research/SKILL.md +75 -0
- package/dist/core/skills/builtin/marketing-campaign/SKILL.md +113 -0
- package/dist/core/skills/builtin/mcp-server-patterns/SKILL.md +69 -0
- package/dist/core/skills/builtin/messages-ops/SKILL.md +104 -0
- package/dist/core/skills/builtin/mle-workflow/SKILL.md +346 -0
- package/dist/core/skills/builtin/motion-advanced/SKILL.md +596 -0
- package/dist/core/skills/builtin/motion-foundations/SKILL.md +299 -0
- package/dist/core/skills/builtin/motion-patterns/SKILL.md +434 -0
- package/dist/core/skills/builtin/motion-ui/SKILL.md +575 -0
- package/dist/core/skills/builtin/mysql-patterns/SKILL.md +412 -0
- package/dist/core/skills/builtin/nanoclaw-repl/SKILL.md +33 -0
- package/dist/core/skills/builtin/nestjs-patterns/SKILL.md +230 -0
- package/dist/core/skills/builtin/netmiko-ssh-automation/SKILL.md +173 -0
- package/dist/core/skills/builtin/network-bgp-diagnostics/SKILL.md +167 -0
- package/dist/core/skills/builtin/network-config-validation/SKILL.md +210 -0
- package/dist/core/skills/builtin/network-interface-health/SKILL.md +152 -0
- package/dist/core/skills/builtin/nextjs-turbopack/SKILL.md +57 -0
- package/dist/core/skills/builtin/nodejs-keccak256/SKILL.md +102 -0
- package/dist/core/skills/builtin/nutrient-document-processing/SKILL.md +167 -0
- package/dist/core/skills/builtin/nuxt4-patterns/SKILL.md +100 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/SKILL.md +288 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/gacha.py +224 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/gacha.sh +5 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/references/avatar-style.md +124 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/references/boundary-rules.md +53 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/references/error-handling.md +53 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/references/identity-tension.md +48 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/references/naming-system.md +39 -0
- package/dist/core/skills/builtin/openclaw-persona-forge/references/output-template.md +166 -0
- package/dist/core/skills/builtin/opensource-pipeline/SKILL.md +255 -0
- package/dist/core/skills/builtin/orch-add-feature/SKILL.md +44 -0
- package/dist/core/skills/builtin/orch-build-mvp/SKILL.md +48 -0
- package/dist/core/skills/builtin/orch-change-feature/SKILL.md +42 -0
- package/dist/core/skills/builtin/orch-fix-defect/SKILL.md +42 -0
- package/dist/core/skills/builtin/orch-pipeline/SKILL.md +120 -0
- package/dist/core/skills/builtin/orch-refine-code/SKILL.md +43 -0
- package/dist/core/skills/builtin/parallel-execution-optimizer/SKILL.md +72 -0
- package/dist/core/skills/builtin/perl-patterns/SKILL.md +504 -0
- package/dist/core/skills/builtin/perl-security/SKILL.md +503 -0
- package/dist/core/skills/builtin/perl-testing/SKILL.md +475 -0
- package/dist/core/skills/builtin/plan-orchestrate/SKILL.md +262 -0
- package/dist/core/skills/builtin/plankton-code-quality/SKILL.md +236 -0
- package/dist/core/skills/builtin/postgres-patterns/SKILL.md +147 -0
- package/dist/core/skills/builtin/prediction-market-oracle-research/SKILL.md +63 -0
- package/dist/core/skills/builtin/prediction-market-risk-review/SKILL.md +60 -0
- package/dist/core/skills/builtin/prisma-patterns/SKILL.md +371 -0
- package/dist/core/skills/builtin/product-capability/SKILL.md +141 -0
- package/dist/core/skills/builtin/product-lens/SKILL.md +92 -0
- package/dist/core/skills/builtin/production-audit/SKILL.md +206 -0
- package/dist/core/skills/builtin/production-scheduling/SKILL.md +238 -0
- package/dist/core/skills/builtin/prompt-optimizer/SKILL.md +398 -0
- package/dist/core/skills/builtin/python-patterns/SKILL.md +750 -0
- package/dist/core/skills/builtin/python-testing/SKILL.md +816 -0
- package/dist/core/skills/builtin/pytorch-patterns/SKILL.md +396 -0
- package/dist/core/skills/builtin/quality-nonconformance/SKILL.md +260 -0
- package/dist/core/skills/builtin/quarkus-patterns/SKILL.md +722 -0
- package/dist/core/skills/builtin/quarkus-security/SKILL.md +467 -0
- package/dist/core/skills/builtin/quarkus-tdd/SKILL.md +811 -0
- package/dist/core/skills/builtin/quarkus-verification/SKILL.md +479 -0
- package/dist/core/skills/builtin/ralphinho-rfc-pipeline/SKILL.md +67 -0
- package/dist/core/skills/builtin/react-patterns/SKILL.md +341 -0
- package/dist/core/skills/builtin/react-performance/SKILL.md +574 -0
- package/dist/core/skills/builtin/react-testing/SKILL.md +423 -0
- package/dist/core/skills/builtin/recsys-pipeline-architect/SKILL.md +114 -0
- package/dist/core/skills/builtin/recursive-decision-ledger/SKILL.md +79 -0
- package/dist/core/skills/builtin/redis-patterns/SKILL.md +403 -0
- package/dist/core/skills/builtin/regex-vs-llm-structured-text/SKILL.md +220 -0
- package/dist/core/skills/builtin/repo-scan/SKILL.md +78 -0
- package/dist/core/skills/builtin/research-ops/SKILL.md +112 -0
- package/dist/core/skills/builtin/returns-reverse-logistics/SKILL.md +240 -0
- package/dist/core/skills/builtin/rules-distill/SKILL.md +264 -0
- package/dist/core/skills/builtin/rules-distill/scripts/scan-rules.sh +58 -0
- package/dist/core/skills/builtin/rules-distill/scripts/scan-skills.sh +129 -0
- package/dist/core/skills/builtin/rust-patterns/SKILL.md +499 -0
- package/dist/core/skills/builtin/rust-testing/SKILL.md +500 -0
- package/dist/core/skills/builtin/safety-guard/SKILL.md +75 -0
- package/dist/core/skills/builtin/santa-method/SKILL.md +306 -0
- package/dist/core/skills/builtin/scientific-db-pubmed-database/SKILL.md +175 -0
- package/dist/core/skills/builtin/scientific-db-uspto-database/SKILL.md +177 -0
- package/dist/core/skills/builtin/scientific-pkg-gget/SKILL.md +166 -0
- package/dist/core/skills/builtin/scientific-thinking-literature-review/SKILL.md +192 -0
- package/dist/core/skills/builtin/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
- package/dist/core/skills/builtin/search-first/SKILL.md +182 -0
- package/dist/core/skills/builtin/security-bounty-hunter/SKILL.md +99 -0
- package/dist/core/skills/builtin/security-review/SKILL.md +503 -0
- package/dist/core/skills/builtin/security-review/cloud-infrastructure-security.md +361 -0
- package/dist/core/skills/builtin/security-scan/SKILL.md +165 -0
- package/dist/core/skills/builtin/seo/SKILL.md +154 -0
- package/dist/core/skills/builtin/skill-comply/SKILL.md +58 -0
- package/dist/core/skills/builtin/skill-comply/fixtures/compliant_trace.jsonl +5 -0
- package/dist/core/skills/builtin/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
- package/dist/core/skills/builtin/skill-comply/fixtures/tdd_spec.yaml +44 -0
- package/dist/core/skills/builtin/skill-comply/prompts/classifier.md +24 -0
- package/dist/core/skills/builtin/skill-comply/prompts/scenario_generator.md +62 -0
- package/dist/core/skills/builtin/skill-comply/prompts/spec_generator.md +42 -0
- package/dist/core/skills/builtin/skill-comply/pyproject.toml +15 -0
- package/dist/core/skills/builtin/skill-comply/scripts/__init__.py +0 -0
- package/dist/core/skills/builtin/skill-comply/scripts/classifier.py +85 -0
- package/dist/core/skills/builtin/skill-comply/scripts/grader.py +124 -0
- package/dist/core/skills/builtin/skill-comply/scripts/parser.py +107 -0
- package/dist/core/skills/builtin/skill-comply/scripts/report.py +170 -0
- package/dist/core/skills/builtin/skill-comply/scripts/run.py +127 -0
- package/dist/core/skills/builtin/skill-comply/scripts/runner.py +186 -0
- package/dist/core/skills/builtin/skill-comply/scripts/scenario_generator.py +70 -0
- package/dist/core/skills/builtin/skill-comply/scripts/spec_generator.py +72 -0
- package/dist/core/skills/builtin/skill-comply/scripts/utils.py +13 -0
- package/dist/core/skills/builtin/skill-comply/tests/test_grader.py +197 -0
- package/dist/core/skills/builtin/skill-comply/tests/test_parser.py +90 -0
- package/dist/core/skills/builtin/skill-comply/tests/test_runner.py +172 -0
- package/dist/core/skills/builtin/skill-scout/SKILL.md +140 -0
- package/dist/core/skills/builtin/skill-stocktake/SKILL.md +194 -0
- package/dist/core/skills/builtin/skill-stocktake/scripts/quick-diff.sh +87 -0
- package/dist/core/skills/builtin/skill-stocktake/scripts/save-results.sh +56 -0
- package/dist/core/skills/builtin/skill-stocktake/scripts/scan.sh +170 -0
- package/dist/core/skills/builtin/springboot-patterns/SKILL.md +314 -0
- package/dist/core/skills/builtin/springboot-security/SKILL.md +272 -0
- package/dist/core/skills/builtin/springboot-tdd/SKILL.md +158 -0
- package/dist/core/skills/builtin/springboot-verification/SKILL.md +231 -0
- package/dist/core/skills/builtin/strategic-compact/SKILL.md +135 -0
- package/dist/core/skills/builtin/swift-actor-persistence/SKILL.md +143 -0
- package/dist/core/skills/builtin/swift-concurrency-6-2/SKILL.md +216 -0
- package/dist/core/skills/builtin/swift-protocol-di-testing/SKILL.md +190 -0
- package/dist/core/skills/builtin/swiftui-patterns/SKILL.md +259 -0
- package/dist/core/skills/builtin/tdd-workflow/SKILL.md +463 -0
- package/dist/core/skills/builtin/team-agent-orchestration/SKILL.md +110 -0
- package/dist/core/skills/builtin/team-builder/SKILL.md +168 -0
- package/dist/core/skills/builtin/terminal-ops/SKILL.md +109 -0
- package/dist/core/skills/builtin/tinystruct-patterns/SKILL.md +203 -0
- package/dist/core/skills/builtin/tinystruct-patterns/references/architecture.md +90 -0
- package/dist/core/skills/builtin/tinystruct-patterns/references/data-handling.md +60 -0
- package/dist/core/skills/builtin/tinystruct-patterns/references/database.md +99 -0
- package/dist/core/skills/builtin/tinystruct-patterns/references/routing.md +64 -0
- package/dist/core/skills/builtin/tinystruct-patterns/references/system-usage.md +97 -0
- package/dist/core/skills/builtin/tinystruct-patterns/references/testing.md +72 -0
- package/dist/core/skills/builtin/token-budget-advisor/SKILL.md +133 -0
- package/dist/core/skills/builtin/ui-demo/SKILL.md +465 -0
- package/dist/core/skills/builtin/ui-to-vue/SKILL.md +134 -0
- package/dist/core/skills/builtin/uncloud/SKILL.md +343 -0
- package/dist/core/skills/builtin/unified-notifications-ops/SKILL.md +187 -0
- package/dist/core/skills/builtin/verification-loop/SKILL.md +126 -0
- package/dist/core/skills/builtin/video-editing/SKILL.md +310 -0
- package/dist/core/skills/builtin/videodb/SKILL.md +374 -0
- package/dist/core/skills/builtin/videodb/reference/api-reference.md +550 -0
- package/dist/core/skills/builtin/videodb/reference/capture-reference.md +407 -0
- package/dist/core/skills/builtin/videodb/reference/capture.md +101 -0
- package/dist/core/skills/builtin/videodb/reference/editor.md +443 -0
- package/dist/core/skills/builtin/videodb/reference/generative.md +331 -0
- package/dist/core/skills/builtin/videodb/reference/rtstream-reference.md +564 -0
- package/dist/core/skills/builtin/videodb/reference/rtstream.md +65 -0
- package/dist/core/skills/builtin/videodb/reference/search.md +230 -0
- package/dist/core/skills/builtin/videodb/reference/streaming.md +406 -0
- package/dist/core/skills/builtin/videodb/reference/use-cases.md +118 -0
- package/dist/core/skills/builtin/videodb/scripts/ws_listener.py +282 -0
- package/dist/core/skills/builtin/visa-doc-translate/README.md +86 -0
- package/dist/core/skills/builtin/visa-doc-translate/SKILL.md +117 -0
- package/dist/core/skills/builtin/vite-patterns/SKILL.md +449 -0
- package/dist/core/skills/builtin/windows-desktop-e2e/SKILL.md +887 -0
- package/dist/core/skills/builtin/x-api/SKILL.md +234 -0
- package/dist/core/skills/loader.js +11 -0
- package/dist/core/skills/loader.js.map +1 -1
- package/dist/core/types.d.ts +6 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/plugins/agents/native/index.d.ts +47 -8
- package/dist/plugins/agents/native/index.d.ts.map +1 -1
- package/dist/plugins/agents/native/index.js +253 -102
- package/dist/plugins/agents/native/index.js.map +1 -1
- package/dist/plugins/agents/native/tool-registry.d.ts +33 -0
- package/dist/plugins/agents/native/tool-registry.d.ts.map +1 -0
- package/dist/plugins/agents/native/tool-registry.js +82 -0
- package/dist/plugins/agents/native/tool-registry.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-client.d.ts.map +1 -1
- package/dist/plugins/messengers/dingtalk/dingtalk-client.js +11 -11
- package/dist/plugins/messengers/dingtalk/dingtalk-client.js.map +1 -1
- package/dist/plugins/messengers/feishu/feishu-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/feishu/feishu-adapter.js +9 -5
- package/dist/plugins/messengers/feishu/feishu-adapter.js.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.js +11 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -1
- package/dist/web/public/assets/{a2a-DczMMkbl.js → a2a-Cll3P4QN.js} +2 -2
- package/dist/web/public/assets/{a2a-DczMMkbl.js.map → a2a-Cll3P4QN.js.map} +1 -1
- package/dist/web/public/assets/{activity-cbLHkzca.js → activity-B7T7YFlD.js} +2 -2
- package/dist/web/public/assets/{activity-cbLHkzca.js.map → activity-B7T7YFlD.js.map} +1 -1
- package/dist/web/public/assets/{admins-C-YsGMj7.js → admins-CN7P018S.js} +2 -2
- package/dist/web/public/assets/{admins-C-YsGMj7.js.map → admins-CN7P018S.js.map} +1 -1
- package/dist/web/public/assets/{agents-BWfov_1-.js → agents-Bqgq7GBF.js} +2 -2
- package/dist/web/public/assets/{agents-BWfov_1-.js.map → agents-Bqgq7GBF.js.map} +1 -1
- package/dist/web/public/assets/{approvals-HSssmXKS.js → approvals-C8IUJQ_A.js} +2 -2
- package/dist/web/public/assets/{approvals-HSssmXKS.js.map → approvals-C8IUJQ_A.js.map} +1 -1
- package/dist/web/public/assets/{arrow-down-BXvC8Al2.js → arrow-down-SLWKqtDc.js} +2 -2
- package/dist/web/public/assets/{arrow-down-BXvC8Al2.js.map → arrow-down-SLWKqtDc.js.map} +1 -1
- package/dist/web/public/assets/{arrow-up-63xELY5Q.js → arrow-up-BOADc9ce.js} +2 -2
- package/dist/web/public/assets/{arrow-up-63xELY5Q.js.map → arrow-up-BOADc9ce.js.map} +1 -1
- package/dist/web/public/assets/{asks-COLEFOvK.js → asks-C-j-DypC.js} +2 -2
- package/dist/web/public/assets/{asks-COLEFOvK.js.map → asks-C-j-DypC.js.map} +1 -1
- package/dist/web/public/assets/{audit-D4ZEiZub.js → audit-DQb-RuXh.js} +2 -2
- package/dist/web/public/assets/{audit-D4ZEiZub.js.map → audit-DQb-RuXh.js.map} +1 -1
- package/dist/web/public/assets/{bell-Cg2Bvv06.js → bell-CV88-ul6.js} +2 -2
- package/dist/web/public/assets/{bell-Cg2Bvv06.js.map → bell-CV88-ul6.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-CEjCzwtd.js → bgjobs-CDrK0d-W.js} +2 -2
- package/dist/web/public/assets/{bgjobs-CEjCzwtd.js.map → bgjobs-CDrK0d-W.js.map} +1 -1
- package/dist/web/public/assets/{brain-euvl6F6C.js → brain-B7HtSOQU.js} +2 -2
- package/dist/web/public/assets/{brain-euvl6F6C.js.map → brain-B7HtSOQU.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-DPWLbCnA.js → briefcase-mdzuIa__.js} +2 -2
- package/dist/web/public/assets/{briefcase-DPWLbCnA.js.map → briefcase-mdzuIa__.js.map} +1 -1
- package/dist/web/public/assets/{browser-ponyfill-BUutOaRz.js → browser-ponyfill-DBWdeCTC.js} +2 -2
- package/dist/web/public/assets/{browser-ponyfill-BUutOaRz.js.map → browser-ponyfill-DBWdeCTC.js.map} +1 -1
- package/dist/web/public/assets/{chat-Dz9kfaxH.js → chat-CSjtY2rN.js} +3 -3
- package/dist/web/public/assets/{chat-Dz9kfaxH.js.map → chat-CSjtY2rN.js.map} +1 -1
- package/dist/web/public/assets/{chevron-left-BeIh5thq.js → chevron-left-uSfPn636.js} +2 -2
- package/dist/web/public/assets/{chevron-left-BeIh5thq.js.map → chevron-left-uSfPn636.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-uP_l9MMb.js → chevron-right-CtelqacW.js} +2 -2
- package/dist/web/public/assets/{chevron-right-uP_l9MMb.js.map → chevron-right-CtelqacW.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-CewnjFgv.js → circle-check-8dbL-u7O.js} +2 -2
- package/dist/web/public/assets/{circle-check-CewnjFgv.js.map → circle-check-8dbL-u7O.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-C2RTc48c.js → circle-check-big-D8-svk9a.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-C2RTc48c.js.map → circle-check-big-D8-svk9a.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-Ccg1HyV-.js → circle-x-rUxzIz5P.js} +2 -2
- package/dist/web/public/assets/{circle-x-Ccg1HyV-.js.map → circle-x-rUxzIz5P.js.map} +1 -1
- package/dist/web/public/assets/{clock-qxbYSynv.js → clock-CG5dlBGB.js} +2 -2
- package/dist/web/public/assets/{clock-qxbYSynv.js.map → clock-CG5dlBGB.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-DmJq4Td9.js → confirm-dialog-DlUsSur3.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-DmJq4Td9.js.map → confirm-dialog-DlUsSur3.js.map} +1 -1
- package/dist/web/public/assets/{copy-DxSHRdbc.js → copy-DnC76wFT.js} +2 -2
- package/dist/web/public/assets/{copy-DxSHRdbc.js.map → copy-DnC76wFT.js.map} +1 -1
- package/dist/web/public/assets/{data-table-S7rIjwdO.js → data-table-DswkWUfG.js} +2 -2
- package/dist/web/public/assets/{data-table-S7rIjwdO.js.map → data-table-DswkWUfG.js.map} +1 -1
- package/dist/web/public/assets/dialog-Ceo4YuXy.js +6 -0
- package/dist/web/public/assets/dialog-Ceo4YuXy.js.map +1 -0
- package/dist/web/public/assets/{download-OhsGtnO-.js → download-DF-46tS4.js} +2 -2
- package/dist/web/public/assets/{download-OhsGtnO-.js.map → download-DF-46tS4.js.map} +1 -1
- package/dist/web/public/assets/{email-C1-HxWLF.js → email-CZee26-_.js} +3 -3
- package/dist/web/public/assets/{email-C1-HxWLF.js.map → email-CZee26-_.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-C-qjOHyu.js → empty-state-D9Hi0Atm.js} +2 -2
- package/dist/web/public/assets/{empty-state-C-qjOHyu.js.map → empty-state-D9Hi0Atm.js.map} +1 -1
- package/dist/web/public/assets/{external-link-DRVp9-lb.js → external-link-D64iZa9P.js} +2 -2
- package/dist/web/public/assets/{external-link-DRVp9-lb.js.map → external-link-D64iZa9P.js.map} +1 -1
- package/dist/web/public/assets/{eye-CFhg5BTa.js → eye-sY6WZb7D.js} +2 -2
- package/dist/web/public/assets/{eye-CFhg5BTa.js.map → eye-sY6WZb7D.js.map} +1 -1
- package/dist/web/public/assets/{facts-CGaLWhzi.js → facts-B7bGGwvi.js} +2 -2
- package/dist/web/public/assets/{facts-CGaLWhzi.js.map → facts-B7bGGwvi.js.map} +1 -1
- package/dist/web/public/assets/{goals-C-dJANmn.js → goals-BfQbsvZv.js} +2 -2
- package/dist/web/public/assets/{goals-C-dJANmn.js.map → goals-BfQbsvZv.js.map} +1 -1
- package/dist/web/public/assets/{health-CWcti5h3.js → health-Ba_mY0Ts.js} +2 -2
- package/dist/web/public/assets/{health-CWcti5h3.js.map → health-Ba_mY0Ts.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-DmGhKR2W.js → heart-pulse-BjikOVwU.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-DmGhKR2W.js.map → heart-pulse-BjikOVwU.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-kLoGBNCo.js → heartbeat-BM8LlPes.js} +2 -2
- package/dist/web/public/assets/{heartbeat-kLoGBNCo.js.map → heartbeat-BM8LlPes.js.map} +1 -1
- package/dist/web/public/assets/{hot-BITDoax1.js → hot-BtuLL6n8.js} +2 -2
- package/dist/web/public/assets/{hot-BITDoax1.js.map → hot-BtuLL6n8.js.map} +1 -1
- package/dist/web/public/assets/index-DEWFfW_Z.js +199 -0
- package/dist/web/public/assets/index-DEWFfW_Z.js.map +1 -0
- package/dist/web/public/assets/{installed-Co9WrtQ7.js → installed-Xr8p31ij.js} +2 -2
- package/dist/web/public/assets/{installed-Co9WrtQ7.js.map → installed-Xr8p31ij.js.map} +1 -1
- package/dist/web/public/assets/{jobs-hdHhBEvi.js → jobs-Ddy81Udm.js} +2 -2
- package/dist/web/public/assets/{jobs-hdHhBEvi.js.map → jobs-Ddy81Udm.js.map} +1 -1
- package/dist/web/public/assets/{layout-CQtbOBag.js → layout-BL74fT-L.js} +2 -2
- package/dist/web/public/assets/{layout-CQtbOBag.js.map → layout-BL74fT-L.js.map} +1 -1
- package/dist/web/public/assets/{layout-bDMXIKIR.js → layout-Bn2qUxcK.js} +2 -2
- package/dist/web/public/assets/{layout-bDMXIKIR.js.map → layout-Bn2qUxcK.js.map} +1 -1
- package/dist/web/public/assets/{layout-BMXC1Uh1.js → layout-Bp4SAA8_.js} +2 -2
- package/dist/web/public/assets/{layout-BMXC1Uh1.js.map → layout-Bp4SAA8_.js.map} +1 -1
- package/dist/web/public/assets/{layout-CysVsySh.js → layout-CZ9pGnW8.js} +2 -2
- package/dist/web/public/assets/{layout-CysVsySh.js.map → layout-CZ9pGnW8.js.map} +1 -1
- package/dist/web/public/assets/{layout-CyBGneZ9.js → layout-pasFRkKV.js} +2 -2
- package/dist/web/public/assets/{layout-CyBGneZ9.js.map → layout-pasFRkKV.js.map} +1 -1
- package/dist/web/public/assets/llm-yp7b5xxL.js +7 -0
- package/dist/web/public/assets/llm-yp7b5xxL.js.map +1 -0
- package/dist/web/public/assets/{loader-circle-9VUMGitw.js → loader-circle-Bbw4pEyE.js} +2 -2
- package/dist/web/public/assets/{loader-circle-9VUMGitw.js.map → loader-circle-Bbw4pEyE.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-BXYvvHry.js → map-pin-DIXHUQgM.js} +2 -2
- package/dist/web/public/assets/{map-pin-BXYvvHry.js.map → map-pin-DIXHUQgM.js.map} +1 -1
- package/dist/web/public/assets/{mcp-BgLdlwSn.js → mcp-DyaljIM_.js} +2 -2
- package/dist/web/public/assets/{mcp-BgLdlwSn.js.map → mcp-DyaljIM_.js.map} +1 -1
- package/dist/web/public/assets/memos-Dkoc157i.js +12 -0
- package/dist/web/public/assets/memos-Dkoc157i.js.map +1 -0
- package/dist/web/public/assets/{messengers-7Phqea62.js → messengers-CcyGDeUI.js} +2 -2
- package/dist/web/public/assets/{messengers-7Phqea62.js.map → messengers-CcyGDeUI.js.map} +1 -1
- package/dist/web/public/assets/{mobile-CV5b6D2W.js → mobile-DqzIv4Xb.js} +2 -2
- package/dist/web/public/assets/{mobile-CV5b6D2W.js.map → mobile-DqzIv4Xb.js.map} +1 -1
- package/dist/web/public/assets/{native-agent-QvIa6LjE.js → native-agent-BQ7WaRGK.js} +2 -2
- package/dist/web/public/assets/{native-agent-QvIa6LjE.js.map → native-agent-BQ7WaRGK.js.map} +1 -1
- package/dist/web/public/assets/{network-BXhEjGhE.js → network-B_yUFAqC.js} +2 -2
- package/dist/web/public/assets/{network-BXhEjGhE.js.map → network-B_yUFAqC.js.map} +1 -1
- package/dist/web/public/assets/{outbox-DHQL7TQb.js → outbox-l8aVOZqO.js} +2 -2
- package/dist/web/public/assets/{outbox-DHQL7TQb.js.map → outbox-l8aVOZqO.js.map} +1 -1
- package/dist/web/public/assets/{pagination-VKuPb1Ot.js → pagination-BAKRGKa9.js} +2 -2
- package/dist/web/public/assets/{pagination-VKuPb1Ot.js.map → pagination-BAKRGKa9.js.map} +1 -1
- package/dist/web/public/assets/{persona-CWug2GLR.js → persona-D3VL9Rg1.js} +2 -2
- package/dist/web/public/assets/{persona-CWug2GLR.js.map → persona-D3VL9Rg1.js.map} +1 -1
- package/dist/web/public/assets/{plans-CZoEs5SY.js → plans-BBB5e9my.js} +2 -2
- package/dist/web/public/assets/{plans-CZoEs5SY.js.map → plans-BBB5e9my.js.map} +1 -1
- package/dist/web/public/assets/{play-CfSn5Vdl.js → play-7-Wd369f.js} +2 -2
- package/dist/web/public/assets/{play-CfSn5Vdl.js.map → play-7-Wd369f.js.map} +1 -1
- package/dist/web/public/assets/{plus-Z8l4CiqJ.js → plus-B0sfZy-j.js} +2 -2
- package/dist/web/public/assets/{plus-Z8l4CiqJ.js.map → plus-B0sfZy-j.js.map} +1 -1
- package/dist/web/public/assets/{policy-CutDSEPW.js → policy-BM1WRXH0.js} +2 -2
- package/dist/web/public/assets/{policy-CutDSEPW.js.map → policy-BM1WRXH0.js.map} +1 -1
- package/dist/web/public/assets/{qr-code-DgU5aiM6.js → qr-code-DcKs5fi3.js} +2 -2
- package/dist/web/public/assets/{qr-code-DgU5aiM6.js.map → qr-code-DcKs5fi3.js.map} +1 -1
- package/dist/web/public/assets/{react-Cb2sDjhD.js → react-DlP5eolq.js} +2 -2
- package/dist/web/public/assets/{react-Cb2sDjhD.js.map → react-DlP5eolq.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-D2CWiyU_.js → refresh-ccw-uNKeBeRl.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-D2CWiyU_.js.map → refresh-ccw-uNKeBeRl.js.map} +1 -1
- package/dist/web/public/assets/{reminders-Cb6Izedg.js → reminders-DHM8K0_O.js} +2 -2
- package/dist/web/public/assets/{reminders-Cb6Izedg.js.map → reminders-DHM8K0_O.js.map} +1 -1
- package/dist/web/public/assets/{save-DB0BDYTs.js → save-qwJa5_SA.js} +2 -2
- package/dist/web/public/assets/{save-DB0BDYTs.js.map → save-qwJa5_SA.js.map} +1 -1
- package/dist/web/public/assets/{schedules-8mSjE14D.js → schedules-Bcd0wbT4.js} +2 -2
- package/dist/web/public/assets/{schedules-8mSjE14D.js.map → schedules-Bcd0wbT4.js.map} +1 -1
- package/dist/web/public/assets/{search-Con69NhG.js → search-BUlzNWrj.js} +2 -2
- package/dist/web/public/assets/{search-Con69NhG.js.map → search-BUlzNWrj.js.map} +1 -1
- package/dist/web/public/assets/{search-B4fHilZ0.js → search-i1tP2maJ.js} +2 -2
- package/dist/web/public/assets/{search-B4fHilZ0.js.map → search-i1tP2maJ.js.map} +1 -1
- package/dist/web/public/assets/{security-BTe3zUg8.js → security-DgJyTT4g.js} +2 -2
- package/dist/web/public/assets/{security-BTe3zUg8.js.map → security-DgJyTT4g.js.map} +1 -1
- package/dist/web/public/assets/{service-C7SqcwfL.js → service-A0Hzear0.js} +2 -2
- package/dist/web/public/assets/{service-C7SqcwfL.js.map → service-A0Hzear0.js.map} +1 -1
- package/dist/web/public/assets/{shield-alert-CKFVsGgI.js → shield-alert-DrnN6fz_.js} +2 -2
- package/dist/web/public/assets/{shield-alert-CKFVsGgI.js.map → shield-alert-DrnN6fz_.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-BSkpyN4D.js → status-badge-Ryzf96Pl.js} +2 -2
- package/dist/web/public/assets/{status-badge-BSkpyN4D.js.map → status-badge-Ryzf96Pl.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-Bel-I1Sk.js → subtasks-Bzh3o3EF.js} +2 -2
- package/dist/web/public/assets/{subtasks-Bel-I1Sk.js.map → subtasks-Bzh3o3EF.js.map} +1 -1
- package/dist/web/public/assets/{table-CPn1MRcy.js → table-BbAOSyc8.js} +2 -2
- package/dist/web/public/assets/{table-CPn1MRcy.js.map → table-BbAOSyc8.js.map} +1 -1
- package/dist/web/public/assets/{topn-Ba3RjcK1.js → topn-DkhYw-Gp.js} +2 -2
- package/dist/web/public/assets/{topn-Ba3RjcK1.js.map → topn-DkhYw-Gp.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-Dfov8aHD.js → trash-2-CA0cLpnU.js} +2 -2
- package/dist/web/public/assets/{trash-2-Dfov8aHD.js.map → trash-2-CA0cLpnU.js.map} +1 -1
- package/dist/web/public/assets/{use-background-tasks-BQrEeUwY.js → use-background-tasks-B64YjlA8.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-BQrEeUwY.js.map → use-background-tasks-B64YjlA8.js.map} +1 -1
- package/dist/web/public/assets/{use-event-stream-DgGpGKop.js → use-event-stream-I1lMFEfh.js} +2 -2
- package/dist/web/public/assets/{use-event-stream-DgGpGKop.js.map → use-event-stream-I1lMFEfh.js.map} +1 -1
- package/dist/web/public/assets/{use-llm-admin-DYekqogG.js → use-llm-admin-DY2axI4D.js} +2 -2
- package/dist/web/public/assets/{use-llm-admin-DYekqogG.js.map → use-llm-admin-DY2axI4D.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-DbJ4pP2Z.js → use-memory-BYEjVWbU.js} +2 -2
- package/dist/web/public/assets/{use-memory-DbJ4pP2Z.js.map → use-memory-BYEjVWbU.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-C2M6WZ9W.js → use-observability-Coj02yDo.js} +2 -2
- package/dist/web/public/assets/{use-observability-C2M6WZ9W.js.map → use-observability-Coj02yDo.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-DMdaoWsB.js → use-settings-i1MhlkyC.js} +2 -2
- package/dist/web/public/assets/{use-settings-DMdaoWsB.js.map → use-settings-i1MhlkyC.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-BHG7h3jQ.js → use-workspace-DgEM35PY.js} +2 -2
- package/dist/web/public/assets/{use-workspace-BHG7h3jQ.js.map → use-workspace-DgEM35PY.js.map} +1 -1
- package/dist/web/public/assets/{useQuery-PdiC7-sY.js → useQuery-CY2iazjN.js} +2 -2
- package/dist/web/public/assets/{useQuery-PdiC7-sY.js.map → useQuery-CY2iazjN.js.map} +1 -1
- package/dist/web/public/assets/{vector-DnZM3OXU.js → vector-Ic76u2hY.js} +2 -2
- package/dist/web/public/assets/{vector-DnZM3OXU.js.map → vector-Ic76u2hY.js.map} +1 -1
- package/dist/web/public/assets/{viewer-Dz6k0YKp.js → viewer-BXbUN1Rl.js} +2 -2
- package/dist/web/public/assets/{viewer-Dz6k0YKp.js.map → viewer-BXbUN1Rl.js.map} +1 -1
- package/dist/web/public/assets/{workspace-BnXrWS3j.js → workspace-CUg0JPn6.js} +3 -3
- package/dist/web/public/assets/{workspace-BnXrWS3j.js.map → workspace-CUg0JPn6.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-CSS_UBEi.js → workspaces-C-wb5FQj.js} +2 -2
- package/dist/web/public/assets/{workspaces-CSS_UBEi.js.map → workspaces-C-wb5FQj.js.map} +1 -1
- package/dist/web/public/assets/{x-DG-JKVw_.js → x-D1iSuoqg.js} +2 -2
- package/dist/web/public/assets/{x-DG-JKVw_.js.map → x-D1iSuoqg.js.map} +1 -1
- package/dist/web/public/index.html +2 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +6 -0
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/public/assets/dialog-bAIDaO-6.js +0 -6
- package/dist/web/public/assets/dialog-bAIDaO-6.js.map +0 -1
- package/dist/web/public/assets/index-O0BQoyzo.js +0 -199
- package/dist/web/public/assets/index-O0BQoyzo.js.map +0 -1
- package/dist/web/public/assets/llm-CPIRNQU2.js +0 -7
- package/dist/web/public/assets/llm-CPIRNQU2.js.map +0 -1
- package/dist/web/public/assets/memos-CfneX9DH.js +0 -12
- package/dist/web/public/assets/memos-CfneX9DH.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{n as A,u as F,j as e
|
|
1
|
+
import{n as A,u as F,j as e,a0 as L,k as I,B as u,I as S,c as z,S as D,f as V,g as X,h as J,i as g,l as m,m as j,L as K}from"./index-DEWFfW_Z.js";import{r as M}from"./react-DlP5eolq.js";import{u as Q,a as Y,f as q}from"./use-settings-i1MhlkyC.js";import{L as H}from"./loader-circle-Bbw4pEyE.js";import{C as G}from"./circle-x-rUxzIz5P.js";import{C as W}from"./circle-check-8dbL-u7O.js";import{R as Z}from"./refresh-ccw-uNKeBeRl.js";import{E as $,a as ee}from"./eye-sY6WZb7D.js";import{X as se}from"./x-D1iSuoqg.js";import{S as ae}from"./save-qwJa5_SA.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
|
-
*/const te=A("Mail",[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2",key:"18n3k1"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7",key:"1ocrg3"}]]),U=["IMHUB_SMTP_HOST","IMHUB_SMTP_PORT","IMHUB_SMTP_USER","IMHUB_SMTP_PASS","IMHUB_SMTP_FROM","IMHUB_SMTP_SECURE"];function v(){return{IMHUB_SMTP_HOST:"",IMHUB_SMTP_PORT:"",IMHUB_SMTP_USER:"",IMHUB_SMTP_PASS:"",IMHUB_SMTP_FROM:"",IMHUB_SMTP_SECURE:"auto"}}function ie(s){const i=(s??"").trim().toLowerCase();return i==="1"||i==="true"||i==="yes"?"true":i==="0"||i==="false"||i==="no"?"false":"auto"}function P(s){return{IMHUB_SMTP_HOST:s.IMHUB_SMTP_HOST??"",IMHUB_SMTP_PORT:s.IMHUB_SMTP_PORT??"",IMHUB_SMTP_USER:s.IMHUB_SMTP_USER??"",IMHUB_SMTP_PASS:s.IMHUB_SMTP_PASS??"",IMHUB_SMTP_FROM:s.IMHUB_SMTP_FROM??"",IMHUB_SMTP_SECURE:ie(s.IMHUB_SMTP_SECURE)}}function B(s){return/\*{3,}/.test(s)}function Me(){const{t:s}=F(["settings","common"]),[i,T]=M.useState(!1),n=Q({reveal:i}),o=Y(),h
|
|
7
|
-
//# sourceMappingURL=email-
|
|
6
|
+
*/const te=A("Mail",[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2",key:"18n3k1"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7",key:"1ocrg3"}]]),U=["IMHUB_SMTP_HOST","IMHUB_SMTP_PORT","IMHUB_SMTP_USER","IMHUB_SMTP_PASS","IMHUB_SMTP_FROM","IMHUB_SMTP_SECURE"];function v(){return{IMHUB_SMTP_HOST:"",IMHUB_SMTP_PORT:"",IMHUB_SMTP_USER:"",IMHUB_SMTP_PASS:"",IMHUB_SMTP_FROM:"",IMHUB_SMTP_SECURE:"auto"}}function ie(s){const i=(s??"").trim().toLowerCase();return i==="1"||i==="true"||i==="yes"?"true":i==="0"||i==="false"||i==="no"?"false":"auto"}function P(s){return{IMHUB_SMTP_HOST:s.IMHUB_SMTP_HOST??"",IMHUB_SMTP_PORT:s.IMHUB_SMTP_PORT??"",IMHUB_SMTP_USER:s.IMHUB_SMTP_USER??"",IMHUB_SMTP_PASS:s.IMHUB_SMTP_PASS??"",IMHUB_SMTP_FROM:s.IMHUB_SMTP_FROM??"",IMHUB_SMTP_SECURE:ie(s.IMHUB_SMTP_SECURE)}}function B(s){return/\*{3,}/.test(s)}function Me(){const{t:s}=F(["settings","common"]),[i,T]=M.useState(!1),n=Q({reveal:i}),o=Y(),h=q(),l=n.data?.env??{},[r,f]=M.useState(v),[b,C]=M.useState("");M.useEffect(()=>{if(!n.data)return;const a=P(l),t=JSON.stringify(a);t!==b&&(f(a),C(t))},[n.dataUpdatedAt]);const _=!!(l.IMHUB_SMTP_HOST&&l.IMHUB_SMTP_USER&&l.IMHUB_SMTP_PASS),N=M.useMemo(()=>{if(!n.data)return!1;const a=P(l);for(const t of U)if(!(t==="IMHUB_SMTP_PASS"&&r[t]&&B(r[t])&&r[t]===a[t])&&r[t]!==a[t])return!0;return!1},[r,l,n.data]);function d(a,t){f(c=>({...c,[a]:t}))}function E(){n.data&&f(P(l))}async function R(){if(!n.data)return;const a=P(l),t={};for(const c of U){const p=r[c],k=a[c];p!==k&&(c==="IMHUB_SMTP_PASS"&&B(p)||(t[c]=p===""?null:p))}if(Object.keys(t).length===0){m.info(s("email.toast.noChanges"));return}try{await o.mutateAsync({updates:t}),m.success(s("email.toast.saved"))}catch(c){m.error(j(c,s).message)}}async function y(){if(!n.data)return;const a={};for(const t of U)a[t]=null;try{await o.mutateAsync({updates:a}),f(v()),m.success(s("email.toast.disabled"))}catch(t){m.error(j(t,s).message)}}async function w(){try{const a=await h.mutateAsync();m.success(a.message)}catch(a){m.error(j(a,s).message)}}const O=h.isPending?e.jsx(H,{className:"h-4 w-4 animate-spin"}):h.isError?e.jsx(G,{className:"h-4 w-4 text-danger"}):h.isSuccess?e.jsx(W,{className:"h-4 w-4 text-success"}):e.jsx(L,{className:"h-4 w-4"});return e.jsxs("div",{className:"mx-auto flex max-w-4xl 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("email.title")}),_?e.jsx(I,{variant:"success",children:s("email.statusOn")}):e.jsx(I,{variant:"outline",children:s("email.statusOff")}),e.jsxs(u,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>void n.refetch(),disabled:n.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[n.isFetching?e.jsx(H,{className:"h-4 w-4 animate-spin"}):e.jsx(Z,{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("email.subtitle")})]}),n.isLoading?e.jsx("div",{className:"h-64 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(te,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("email.cardTitle")}),e.jsxs(u,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>T(a=>!a),disabled:n.isFetching,"aria-label":s(i?"email.hide":"email.reveal"),children:[i?e.jsx($,{className:"h-4 w-4"}):e.jsx(ee,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s(i?"email.hide":"email.reveal")})]})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 px-4 py-4 sm:grid-cols-2",children:[e.jsx(x,{label:s("email.host"),hint:s("email.hostHint"),children:e.jsx(S,{value:r.IMHUB_SMTP_HOST,onChange:a=>d("IMHUB_SMTP_HOST",a.target.value),placeholder:"smtp.gmail.com",autoComplete:"off"})}),e.jsx(x,{label:s("email.port"),hint:s("email.portHint"),children:e.jsx(S,{type:"number",inputMode:"numeric",min:1,max:65535,value:r.IMHUB_SMTP_PORT,onChange:a=>d("IMHUB_SMTP_PORT",a.target.value),placeholder:"465",autoComplete:"off"})}),e.jsx(x,{label:s("email.user"),hint:s("email.userHint"),children:e.jsx(S,{value:r.IMHUB_SMTP_USER,onChange:a=>d("IMHUB_SMTP_USER",a.target.value),placeholder:"you@example.com",autoComplete:"off"})}),e.jsx(x,{label:s("email.pass"),hint:s("email.passHint"),children:e.jsx(S,{type:i?"text":"password",value:r.IMHUB_SMTP_PASS,onChange:a=>d("IMHUB_SMTP_PASS",a.target.value),placeholder:"••••••••",autoComplete:"new-password",className:z(B(r.IMHUB_SMTP_PASS)&&"font-mono text-text-muted")})}),e.jsx(x,{label:s("email.from"),hint:s("email.fromHint"),children:e.jsx(S,{value:r.IMHUB_SMTP_FROM,onChange:a=>d("IMHUB_SMTP_FROM",a.target.value),placeholder:"",autoComplete:"off"})}),e.jsx(x,{label:s("email.secure"),hint:s("email.secureHint"),children:e.jsxs(D,{value:r.IMHUB_SMTP_SECURE,onValueChange:a=>d("IMHUB_SMTP_SECURE",a),children:[e.jsx(V,{children:e.jsx(X,{})}),e.jsxs(J,{children:[e.jsx(g,{value:"auto",children:s("email.secureAuto")}),e.jsx(g,{value:"true",children:s("email.secureTrue")}),e.jsx(g,{value:"false",children:s("email.secureFalse")})]})]})})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 border-t border-border px-4 py-3",children:[e.jsxs(u,{variant:"secondary",size:"sm",onClick:()=>void w(),disabled:!_||h.isPending,title:_?void 0:s("email.testNeedsConfigured"),children:[O,s("email.testBtn")]}),e.jsxs(u,{variant:"ghost",size:"sm",onClick:()=>void y(),disabled:!_||o.isPending,className:"text-danger hover:text-danger",children:[e.jsx(se,{className:"h-4 w-4"}),s("email.disableBtn")]}),e.jsx("span",{className:"ml-auto"}),N&&e.jsxs(e.Fragment,{children:[e.jsx(u,{variant:"ghost",size:"sm",onClick:E,disabled:o.isPending,children:s("email.discard")}),e.jsxs(u,{size:"sm",onClick:()=>void R(),disabled:o.isPending,children:[o.isPending?e.jsx(H,{className:"h-4 w-4 animate-spin"}):e.jsx(ae,{className:"h-4 w-4"}),o.isPending?s("email.saving"):s("email.saveBtn")]})]})]})]})]})}function x({label:s,hint:i,children:T}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(K,{className:"text-xs font-medium",children:s}),T,i&&e.jsx("p",{className:"text-[11px] text-text-dim",children:i})]})}export{Me as default,ie as normalizeSecure};
|
|
7
|
+
//# sourceMappingURL=email-CZee26-_.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-C1-HxWLF.js","sources":["../../node_modules/lucide-react/dist/esm/icons/mail.js","../../src/routes/settings/email.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 Mail = createLucideIcon(\"Mail\", [\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }],\n [\"path\", { d: \"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\", key: \"1ocrg3\" }]\n]);\n\nexport { Mail as default };\n//# sourceMappingURL=mail.js.map\n","/**\n * /settings/email — SMTP credentials editor (matches v1 settings.html's\n * \"📨 SMTP\" card). Drives email delivery for `/remind email me@x.com …`.\n *\n * Six env keys, persisted to `~/.agim/.env`:\n * * IMHUB_SMTP_HOST / PORT / USER / PASS / FROM / SECURE\n *\n * IMHUB_SMTP_PASS is in the backend's SECRET_KEYS set — masked unless\n * the Reveal toggle issues a `?reveal=1` fetch. Submitting a masked\n * string back is a no-op on the backend (it preserves the real value).\n *\n * Test button calls POST /api/messengers/email/test which runs\n * `nodemailer.verify()` against the live env (i.e. the operator must\n * Save first, then Test — same UX as v1).\n *\n * Disable button clears all six keys via a single PUT /api/env with\n * null values; the email adapter then logs `email.disabled` on the\n * next service restart.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n CheckCircle2, Eye, EyeOff, Loader2, Mail, RefreshCcw,\n Save, Send, X, XCircle,\n} from 'lucide-react'\n\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 Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv, useTestEmail } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\nconst SMTP_KEYS = [\n 'IMHUB_SMTP_HOST',\n 'IMHUB_SMTP_PORT',\n 'IMHUB_SMTP_USER',\n 'IMHUB_SMTP_PASS',\n 'IMHUB_SMTP_FROM',\n 'IMHUB_SMTP_SECURE',\n] as const\n\ntype SmtpKey = typeof SMTP_KEYS[number]\ntype SecureMode = 'auto' | 'true' | 'false'\n\ninterface Draft {\n IMHUB_SMTP_HOST: string\n IMHUB_SMTP_PORT: string\n IMHUB_SMTP_USER: string\n IMHUB_SMTP_PASS: string\n IMHUB_SMTP_FROM: string\n IMHUB_SMTP_SECURE: SecureMode\n}\n\nfunction emptyDraft(): Draft {\n return {\n IMHUB_SMTP_HOST: '',\n IMHUB_SMTP_PORT: '',\n IMHUB_SMTP_USER: '',\n IMHUB_SMTP_PASS: '',\n IMHUB_SMTP_FROM: '',\n IMHUB_SMTP_SECURE: 'auto',\n }\n}\n\n// R13: exported so the unit suite can lock the env-string → SecureMode\n// mapping without spinning up Radix Select (whose trigger label isn't\n// readable in jsdom). Mirrors the operator's mental model: anything\n// that reads as \"yes/true/on\" maps to true; \"no/false/off\" to false;\n// blank / unknown to auto (defer to port-based heuristic at send time).\nexport function normalizeSecure(raw: string | undefined): SecureMode {\n const v = (raw ?? '').trim().toLowerCase()\n if (v === '1' || v === 'true' || v === 'yes') return 'true'\n if (v === '0' || v === 'false' || v === 'no') return 'false'\n return 'auto'\n}\n\nfunction draftFromEnv(env: Record<string, string>): Draft {\n return {\n IMHUB_SMTP_HOST: env.IMHUB_SMTP_HOST ?? '',\n IMHUB_SMTP_PORT: env.IMHUB_SMTP_PORT ?? '',\n IMHUB_SMTP_USER: env.IMHUB_SMTP_USER ?? '',\n IMHUB_SMTP_PASS: env.IMHUB_SMTP_PASS ?? '',\n IMHUB_SMTP_FROM: env.IMHUB_SMTP_FROM ?? '',\n IMHUB_SMTP_SECURE: normalizeSecure(env.IMHUB_SMTP_SECURE),\n }\n}\n\n/** Detect the backend's secret-mask format: `ab****yz` (3+ `*` between\n * surrounding chars). PUT /api/env preserves the real value when it\n * sees this pattern, so client edits that just echo the mask are a\n * no-op — we skip them in the dirty check + the submit body. */\nfunction isMasked(s: string): boolean {\n return /\\*{3,}/.test(s)\n}\n\nexport default function SettingsEmailRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n\n const [reveal, setReveal] = useState(false)\n const envQuery = useEnv({ reveal })\n const updateEnv = useUpdateEnv()\n const testMut = useTestEmail()\n\n const env = envQuery.data?.env ?? {}\n\n const [draft, setDraft] = useState<Draft>(emptyDraft)\n // Sync draft from server whenever a fresh env arrives (initial load\n // + reveal toggle + post-save refetch). Local edits that diverge stay\n // until the user Saves or Discards.\n const [syncedHash, setSyncedHash] = useState<string>('')\n useEffect(() => {\n if (!envQuery.data) return\n const next = draftFromEnv(env)\n const hash = JSON.stringify(next)\n if (hash !== syncedHash) {\n setDraft(next)\n setSyncedHash(hash)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [envQuery.dataUpdatedAt])\n\n const isConfigured = !!(env.IMHUB_SMTP_HOST && env.IMHUB_SMTP_USER && env.IMHUB_SMTP_PASS)\n\n const isDirty = useMemo(() => {\n if (!envQuery.data) return false\n const current = draftFromEnv(env)\n for (const k of SMTP_KEYS) {\n // PASS: ignore \"user just echoed the mask back\" as no-change.\n if (k === 'IMHUB_SMTP_PASS' && draft[k] && isMasked(draft[k]) && draft[k] === current[k]) continue\n if (draft[k] !== current[k]) return true\n }\n return false\n }, [draft, env, envQuery.data])\n\n function setField<K extends SmtpKey>(key: K, value: Draft[K]): void {\n setDraft((d) => ({ ...d, [key]: value }))\n }\n\n function onDiscard(): void {\n if (!envQuery.data) return\n setDraft(draftFromEnv(env))\n }\n\n async function onSave(): Promise<void> {\n if (!envQuery.data) return\n const current = draftFromEnv(env)\n const updates: Record<string, string | null> = {}\n for (const k of SMTP_KEYS) {\n const next = draft[k]\n const cur = current[k]\n if (next === cur) continue\n // Don't ship a masked PASS as the new value — backend's\n // isMasked-detect already skips it server-side, but keep the\n // wire honest.\n if (k === 'IMHUB_SMTP_PASS' && isMasked(next)) continue\n // Empty string → null (explicit unset) for non-PASS fields.\n // For PASS, an empty string also means \"clear\" (Disable button uses\n // the same path).\n updates[k] = next === '' ? null : next\n }\n if (Object.keys(updates).length === 0) {\n toast.info(t('email.toast.noChanges'))\n return\n }\n try {\n await updateEnv.mutateAsync({ updates })\n toast.success(t('email.toast.saved'))\n // refetch handled by hook's onSuccess; draft will re-sync via\n // the dataUpdatedAt effect on the next paint.\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onDisable(): Promise<void> {\n if (!envQuery.data) return\n const updates: Record<string, string | null> = {}\n for (const k of SMTP_KEYS) updates[k] = null\n try {\n await updateEnv.mutateAsync({ updates })\n setDraft(emptyDraft())\n toast.success(t('email.toast.disabled'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onTest(): Promise<void> {\n try {\n const res = await testMut.mutateAsync()\n toast.success(res.message)\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const testIcon =\n testMut.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : testMut.isError ? <XCircle className=\"h-4 w-4 text-danger\" />\n : testMut.isSuccess ? <CheckCircle2 className=\"h-4 w-4 text-success\" />\n : <Send className=\"h-4 w-4\" />\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('email.title')}</h1>\n {isConfigured\n ? <Badge variant=\"success\">{t('email.statusOn')}</Badge>\n : <Badge variant=\"outline\">{t('email.statusOff')}</Badge>}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => void envQuery.refetch()}\n disabled={envQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <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('email.subtitle')}</p>\n </header>\n\n {envQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\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 <Mail className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('email.cardTitle')}</h2>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => setReveal((v) => !v)}\n disabled={envQuery.isFetching}\n aria-label={reveal ? t('email.hide') : t('email.reveal')}\n >\n {reveal ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{reveal ? t('email.hide') : t('email.reveal')}</span>\n </Button>\n </header>\n\n <div className=\"grid grid-cols-1 gap-3 px-4 py-4 sm:grid-cols-2\">\n <Field label={t('email.host')} hint={t('email.hostHint')}>\n <Input\n value={draft.IMHUB_SMTP_HOST}\n onChange={(e) => setField('IMHUB_SMTP_HOST', e.target.value)}\n placeholder=\"smtp.gmail.com\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.port')} hint={t('email.portHint')}>\n <Input\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={65535}\n value={draft.IMHUB_SMTP_PORT}\n onChange={(e) => setField('IMHUB_SMTP_PORT', e.target.value)}\n placeholder=\"465\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.user')} hint={t('email.userHint')}>\n <Input\n value={draft.IMHUB_SMTP_USER}\n onChange={(e) => setField('IMHUB_SMTP_USER', e.target.value)}\n placeholder=\"you@example.com\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.pass')} hint={t('email.passHint')}>\n <Input\n type={reveal ? 'text' : 'password'}\n value={draft.IMHUB_SMTP_PASS}\n onChange={(e) => setField('IMHUB_SMTP_PASS', e.target.value)}\n placeholder=\"••••••••\"\n autoComplete=\"new-password\"\n className={cn(isMasked(draft.IMHUB_SMTP_PASS) && 'font-mono text-text-muted')}\n />\n </Field>\n <Field label={t('email.from')} hint={t('email.fromHint')}>\n <Input\n value={draft.IMHUB_SMTP_FROM}\n onChange={(e) => setField('IMHUB_SMTP_FROM', e.target.value)}\n placeholder=\"\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.secure')} hint={t('email.secureHint')}>\n <Select\n value={draft.IMHUB_SMTP_SECURE}\n onValueChange={(v) => setField('IMHUB_SMTP_SECURE', v as SecureMode)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"auto\">{t('email.secureAuto')}</SelectItem>\n <SelectItem value=\"true\">{t('email.secureTrue')}</SelectItem>\n <SelectItem value=\"false\">{t('email.secureFalse')}</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2 border-t border-border px-4 py-3\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => void onTest()}\n disabled={!isConfigured || testMut.isPending}\n title={!isConfigured ? t('email.testNeedsConfigured') : undefined}\n >\n {testIcon}\n {t('email.testBtn')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => void onDisable()}\n disabled={!isConfigured || updateEnv.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <X className=\"h-4 w-4\" />\n {t('email.disableBtn')}\n </Button>\n <span className=\"ml-auto\" />\n {isDirty && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onDiscard}\n disabled={updateEnv.isPending}\n >\n {t('email.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateEnv.isPending}\n >\n {updateEnv.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {updateEnv.isPending ? t('email.saving') : t('email.saveBtn')}\n </Button>\n </>\n )}\n </div>\n </section>\n )}\n </div>\n )\n}\n\ninterface FieldProps {\n label: string\n hint?: string\n children: React.ReactNode\n}\n\nfunction Field({ label, hint, children }: FieldProps): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">{label}</Label>\n {children}\n {hint && <p className=\"text-[11px] text-text-dim\">{hint}</p>}\n </div>\n )\n}\n"],"names":["Mail","createLucideIcon","SMTP_KEYS","emptyDraft","normalizeSecure","raw","v","draftFromEnv","env","isMasked","SettingsEmailRoute","t","useTranslation","reveal","setReveal","useState","envQuery","useEnv","updateEnv","useUpdateEnv","testMut","useTestEmail","draft","setDraft","syncedHash","setSyncedHash","useEffect","next","hash","isConfigured","isDirty","useMemo","current","k","setField","key","value","d","onDiscard","onSave","updates","cur","toast","err","describeError","onDisable","onTest","res","testIcon","jsx","Loader2","XCircle","CheckCircle2","Send","jsxs","Badge","Button","RefreshCcw","EyeOff","Eye","Field","Input","e","cn","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","X","Fragment","Save","label","hint","children","Label"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"email-CZee26-_.js","sources":["../../node_modules/lucide-react/dist/esm/icons/mail.js","../../src/routes/settings/email.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 Mail = createLucideIcon(\"Mail\", [\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }],\n [\"path\", { d: \"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\", key: \"1ocrg3\" }]\n]);\n\nexport { Mail as default };\n//# sourceMappingURL=mail.js.map\n","/**\n * /settings/email — SMTP credentials editor (matches v1 settings.html's\n * \"📨 SMTP\" card). Drives email delivery for `/remind email me@x.com …`.\n *\n * Six env keys, persisted to `~/.agim/.env`:\n * * IMHUB_SMTP_HOST / PORT / USER / PASS / FROM / SECURE\n *\n * IMHUB_SMTP_PASS is in the backend's SECRET_KEYS set — masked unless\n * the Reveal toggle issues a `?reveal=1` fetch. Submitting a masked\n * string back is a no-op on the backend (it preserves the real value).\n *\n * Test button calls POST /api/messengers/email/test which runs\n * `nodemailer.verify()` against the live env (i.e. the operator must\n * Save first, then Test — same UX as v1).\n *\n * Disable button clears all six keys via a single PUT /api/env with\n * null values; the email adapter then logs `email.disabled` on the\n * next service restart.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n CheckCircle2, Eye, EyeOff, Loader2, Mail, RefreshCcw,\n Save, Send, X, XCircle,\n} from 'lucide-react'\n\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 Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv, useTestEmail } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\nconst SMTP_KEYS = [\n 'IMHUB_SMTP_HOST',\n 'IMHUB_SMTP_PORT',\n 'IMHUB_SMTP_USER',\n 'IMHUB_SMTP_PASS',\n 'IMHUB_SMTP_FROM',\n 'IMHUB_SMTP_SECURE',\n] as const\n\ntype SmtpKey = typeof SMTP_KEYS[number]\ntype SecureMode = 'auto' | 'true' | 'false'\n\ninterface Draft {\n IMHUB_SMTP_HOST: string\n IMHUB_SMTP_PORT: string\n IMHUB_SMTP_USER: string\n IMHUB_SMTP_PASS: string\n IMHUB_SMTP_FROM: string\n IMHUB_SMTP_SECURE: SecureMode\n}\n\nfunction emptyDraft(): Draft {\n return {\n IMHUB_SMTP_HOST: '',\n IMHUB_SMTP_PORT: '',\n IMHUB_SMTP_USER: '',\n IMHUB_SMTP_PASS: '',\n IMHUB_SMTP_FROM: '',\n IMHUB_SMTP_SECURE: 'auto',\n }\n}\n\n// R13: exported so the unit suite can lock the env-string → SecureMode\n// mapping without spinning up Radix Select (whose trigger label isn't\n// readable in jsdom). Mirrors the operator's mental model: anything\n// that reads as \"yes/true/on\" maps to true; \"no/false/off\" to false;\n// blank / unknown to auto (defer to port-based heuristic at send time).\nexport function normalizeSecure(raw: string | undefined): SecureMode {\n const v = (raw ?? '').trim().toLowerCase()\n if (v === '1' || v === 'true' || v === 'yes') return 'true'\n if (v === '0' || v === 'false' || v === 'no') return 'false'\n return 'auto'\n}\n\nfunction draftFromEnv(env: Record<string, string>): Draft {\n return {\n IMHUB_SMTP_HOST: env.IMHUB_SMTP_HOST ?? '',\n IMHUB_SMTP_PORT: env.IMHUB_SMTP_PORT ?? '',\n IMHUB_SMTP_USER: env.IMHUB_SMTP_USER ?? '',\n IMHUB_SMTP_PASS: env.IMHUB_SMTP_PASS ?? '',\n IMHUB_SMTP_FROM: env.IMHUB_SMTP_FROM ?? '',\n IMHUB_SMTP_SECURE: normalizeSecure(env.IMHUB_SMTP_SECURE),\n }\n}\n\n/** Detect the backend's secret-mask format: `ab****yz` (3+ `*` between\n * surrounding chars). PUT /api/env preserves the real value when it\n * sees this pattern, so client edits that just echo the mask are a\n * no-op — we skip them in the dirty check + the submit body. */\nfunction isMasked(s: string): boolean {\n return /\\*{3,}/.test(s)\n}\n\nexport default function SettingsEmailRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n\n const [reveal, setReveal] = useState(false)\n const envQuery = useEnv({ reveal })\n const updateEnv = useUpdateEnv()\n const testMut = useTestEmail()\n\n const env = envQuery.data?.env ?? {}\n\n const [draft, setDraft] = useState<Draft>(emptyDraft)\n // Sync draft from server whenever a fresh env arrives (initial load\n // + reveal toggle + post-save refetch). Local edits that diverge stay\n // until the user Saves or Discards.\n const [syncedHash, setSyncedHash] = useState<string>('')\n useEffect(() => {\n if (!envQuery.data) return\n const next = draftFromEnv(env)\n const hash = JSON.stringify(next)\n if (hash !== syncedHash) {\n setDraft(next)\n setSyncedHash(hash)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [envQuery.dataUpdatedAt])\n\n const isConfigured = !!(env.IMHUB_SMTP_HOST && env.IMHUB_SMTP_USER && env.IMHUB_SMTP_PASS)\n\n const isDirty = useMemo(() => {\n if (!envQuery.data) return false\n const current = draftFromEnv(env)\n for (const k of SMTP_KEYS) {\n // PASS: ignore \"user just echoed the mask back\" as no-change.\n if (k === 'IMHUB_SMTP_PASS' && draft[k] && isMasked(draft[k]) && draft[k] === current[k]) continue\n if (draft[k] !== current[k]) return true\n }\n return false\n }, [draft, env, envQuery.data])\n\n function setField<K extends SmtpKey>(key: K, value: Draft[K]): void {\n setDraft((d) => ({ ...d, [key]: value }))\n }\n\n function onDiscard(): void {\n if (!envQuery.data) return\n setDraft(draftFromEnv(env))\n }\n\n async function onSave(): Promise<void> {\n if (!envQuery.data) return\n const current = draftFromEnv(env)\n const updates: Record<string, string | null> = {}\n for (const k of SMTP_KEYS) {\n const next = draft[k]\n const cur = current[k]\n if (next === cur) continue\n // Don't ship a masked PASS as the new value — backend's\n // isMasked-detect already skips it server-side, but keep the\n // wire honest.\n if (k === 'IMHUB_SMTP_PASS' && isMasked(next)) continue\n // Empty string → null (explicit unset) for non-PASS fields.\n // For PASS, an empty string also means \"clear\" (Disable button uses\n // the same path).\n updates[k] = next === '' ? null : next\n }\n if (Object.keys(updates).length === 0) {\n toast.info(t('email.toast.noChanges'))\n return\n }\n try {\n await updateEnv.mutateAsync({ updates })\n toast.success(t('email.toast.saved'))\n // refetch handled by hook's onSuccess; draft will re-sync via\n // the dataUpdatedAt effect on the next paint.\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onDisable(): Promise<void> {\n if (!envQuery.data) return\n const updates: Record<string, string | null> = {}\n for (const k of SMTP_KEYS) updates[k] = null\n try {\n await updateEnv.mutateAsync({ updates })\n setDraft(emptyDraft())\n toast.success(t('email.toast.disabled'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onTest(): Promise<void> {\n try {\n const res = await testMut.mutateAsync()\n toast.success(res.message)\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const testIcon =\n testMut.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : testMut.isError ? <XCircle className=\"h-4 w-4 text-danger\" />\n : testMut.isSuccess ? <CheckCircle2 className=\"h-4 w-4 text-success\" />\n : <Send className=\"h-4 w-4\" />\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('email.title')}</h1>\n {isConfigured\n ? <Badge variant=\"success\">{t('email.statusOn')}</Badge>\n : <Badge variant=\"outline\">{t('email.statusOff')}</Badge>}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => void envQuery.refetch()}\n disabled={envQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <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('email.subtitle')}</p>\n </header>\n\n {envQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\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 <Mail className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('email.cardTitle')}</h2>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => setReveal((v) => !v)}\n disabled={envQuery.isFetching}\n aria-label={reveal ? t('email.hide') : t('email.reveal')}\n >\n {reveal ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{reveal ? t('email.hide') : t('email.reveal')}</span>\n </Button>\n </header>\n\n <div className=\"grid grid-cols-1 gap-3 px-4 py-4 sm:grid-cols-2\">\n <Field label={t('email.host')} hint={t('email.hostHint')}>\n <Input\n value={draft.IMHUB_SMTP_HOST}\n onChange={(e) => setField('IMHUB_SMTP_HOST', e.target.value)}\n placeholder=\"smtp.gmail.com\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.port')} hint={t('email.portHint')}>\n <Input\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={65535}\n value={draft.IMHUB_SMTP_PORT}\n onChange={(e) => setField('IMHUB_SMTP_PORT', e.target.value)}\n placeholder=\"465\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.user')} hint={t('email.userHint')}>\n <Input\n value={draft.IMHUB_SMTP_USER}\n onChange={(e) => setField('IMHUB_SMTP_USER', e.target.value)}\n placeholder=\"you@example.com\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.pass')} hint={t('email.passHint')}>\n <Input\n type={reveal ? 'text' : 'password'}\n value={draft.IMHUB_SMTP_PASS}\n onChange={(e) => setField('IMHUB_SMTP_PASS', e.target.value)}\n placeholder=\"••••••••\"\n autoComplete=\"new-password\"\n className={cn(isMasked(draft.IMHUB_SMTP_PASS) && 'font-mono text-text-muted')}\n />\n </Field>\n <Field label={t('email.from')} hint={t('email.fromHint')}>\n <Input\n value={draft.IMHUB_SMTP_FROM}\n onChange={(e) => setField('IMHUB_SMTP_FROM', e.target.value)}\n placeholder=\"\"\n autoComplete=\"off\"\n />\n </Field>\n <Field label={t('email.secure')} hint={t('email.secureHint')}>\n <Select\n value={draft.IMHUB_SMTP_SECURE}\n onValueChange={(v) => setField('IMHUB_SMTP_SECURE', v as SecureMode)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"auto\">{t('email.secureAuto')}</SelectItem>\n <SelectItem value=\"true\">{t('email.secureTrue')}</SelectItem>\n <SelectItem value=\"false\">{t('email.secureFalse')}</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2 border-t border-border px-4 py-3\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => void onTest()}\n disabled={!isConfigured || testMut.isPending}\n title={!isConfigured ? t('email.testNeedsConfigured') : undefined}\n >\n {testIcon}\n {t('email.testBtn')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => void onDisable()}\n disabled={!isConfigured || updateEnv.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <X className=\"h-4 w-4\" />\n {t('email.disableBtn')}\n </Button>\n <span className=\"ml-auto\" />\n {isDirty && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onDiscard}\n disabled={updateEnv.isPending}\n >\n {t('email.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateEnv.isPending}\n >\n {updateEnv.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {updateEnv.isPending ? t('email.saving') : t('email.saveBtn')}\n </Button>\n </>\n )}\n </div>\n </section>\n )}\n </div>\n )\n}\n\ninterface FieldProps {\n label: string\n hint?: string\n children: React.ReactNode\n}\n\nfunction Field({ label, hint, children }: FieldProps): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">{label}</Label>\n {children}\n {hint && <p className=\"text-[11px] text-text-dim\">{hint}</p>}\n </div>\n )\n}\n"],"names":["Mail","createLucideIcon","SMTP_KEYS","emptyDraft","normalizeSecure","raw","v","draftFromEnv","env","isMasked","SettingsEmailRoute","t","useTranslation","reveal","setReveal","useState","envQuery","useEnv","updateEnv","useUpdateEnv","testMut","useTestEmail","draft","setDraft","syncedHash","setSyncedHash","useEffect","next","hash","isConfigured","isDirty","useMemo","current","k","setField","key","value","d","onDiscard","onSave","updates","cur","toast","err","describeError","onDisable","onTest","res","testIcon","jsx","Loader2","XCircle","CheckCircle2","Send","jsxs","Badge","Button","RefreshCcw","EyeOff","Eye","Field","Input","e","cn","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","X","Fragment","Save","label","hint","children","Label"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e,c as x}from"./index-
|
|
2
|
-
//# sourceMappingURL=empty-state-
|
|
1
|
+
import{j as e,c as x}from"./index-DEWFfW_Z.js";function i({icon:t,title:m,description:s,children:a,className:r,...c}){return e.jsxs("div",{className:x("flex flex-col items-center justify-center text-center","py-12 px-4 gap-3",r),...c,children:[t&&e.jsx("div",{className:x("flex items-center justify-center","h-12 w-12 rounded-full bg-surface-2 text-text-dim","[&_svg]:h-6 [&_svg]:w-6"),"aria-hidden":"true",children:t}),e.jsx("h3",{className:"text-base font-semibold text-text",children:m}),s&&e.jsx("p",{className:"text-sm text-text-dim max-w-sm",children:s}),a&&e.jsx("div",{className:"mt-2 flex flex-wrap items-center justify-center gap-2",children:a})]})}i.displayName="EmptyState";export{i as E};
|
|
2
|
+
//# sourceMappingURL=empty-state-D9Hi0Atm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empty-state-
|
|
1
|
+
{"version":3,"file":"empty-state-D9Hi0Atm.js","sources":["../../src/components/common/empty-state.tsx"],"sourcesContent":["/**\n * EmptyState — placeholder shown when a list / table / panel has no\n * rows yet. Used by DataTable's empty branch, by the chat welcome\n * screen (when no messages), and by route bodies that point at an\n * unconfigured / unused subsystem.\n *\n * Slots:\n * icon — optional lucide-react icon node. Sits above the\n * title. Renders inside a soft surface-2 circle so\n * the icon doesn't look stranded on a blank page.\n * title — required short headline (\"No jobs yet\").\n * description — optional sub-line; can wrap.\n * children — optional action slot for one or two Buttons / Links\n * (\"Create your first job\", \"Read the docs\").\n *\n * Visual: centered column, generous vertical padding, max-width on\n * description so wrapping looks intentional on wide screens.\n */\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n icon?: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n}\n\nfunction EmptyState({\n icon,\n title,\n description,\n children,\n className,\n ...props\n}: EmptyStateProps): JSX.Element {\n return (\n <div\n className={cn(\n 'flex flex-col items-center justify-center text-center',\n 'py-12 px-4 gap-3',\n className,\n )}\n {...props}\n >\n {icon && (\n <div\n className={cn(\n 'flex items-center justify-center',\n 'h-12 w-12 rounded-full bg-surface-2 text-text-dim',\n '[&_svg]:h-6 [&_svg]:w-6',\n )}\n aria-hidden=\"true\"\n >\n {icon}\n </div>\n )}\n <h3 className=\"text-base font-semibold text-text\">{title}</h3>\n {description && (\n <p className=\"text-sm text-text-dim max-w-sm\">{description}</p>\n )}\n {children && <div className=\"mt-2 flex flex-wrap items-center justify-center gap-2\">{children}</div>}\n </div>\n )\n}\nEmptyState.displayName = 'EmptyState'\n\nexport { EmptyState }\n"],"names":["EmptyState","icon","title","description","children","className","props","jsxs","cn","jsx"],"mappings":"+CA4BA,SAASA,EAAW,CAClB,KAAAC,EACA,MAAAC,EACA,YAAAC,EACA,SAAAC,EACA,UAAAC,EACA,GAAGC,CACL,EAAiC,CAC/B,OACEC,EAAAA,KAAC,MAAA,CACC,UAAWC,EACT,wDACA,mBACAH,CAAA,EAED,GAAGC,EAEH,SAAA,CAAAL,GACCQ,EAAAA,IAAC,MAAA,CACC,UAAWD,EACT,mCACA,oDACA,yBAAA,EAEF,cAAY,OAEX,SAAAP,CAAA,CAAA,EAGLQ,EAAAA,IAAC,KAAA,CAAG,UAAU,oCAAqC,SAAAP,EAAM,EACxDC,GACCM,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAkC,SAAAN,EAAY,EAE5DC,GAAYK,EAAAA,IAAC,MAAA,CAAI,UAAU,wDAAyD,SAAAL,CAAA,CAAS,CAAA,CAAA,CAAA,CAGpG,CACAJ,EAAW,YAAc"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{n as a}from"./index-
|
|
1
|
+
import{n as a}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 e=a("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);export{e as E};
|
|
7
|
-
//# sourceMappingURL=external-link-
|
|
7
|
+
//# sourceMappingURL=external-link-D64iZa9P.js.map
|
package/dist/web/public/assets/{external-link-DRVp9-lb.js.map → external-link-D64iZa9P.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-link-
|
|
1
|
+
{"version":3,"file":"external-link-D64iZa9P.js","sources":["../../node_modules/lucide-react/dist/esm/icons/external-link.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 ExternalLink = createLucideIcon(\"ExternalLink\", [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"M10 14 21 3\", key: \"gplh6r\" }],\n [\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\", key: \"a6xqqp\" }]\n]);\n\nexport { ExternalLink as default };\n//# sourceMappingURL=external-link.js.map\n"],"names":["ExternalLink","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAeC,EAAiB,eAAgB,CACpD,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,cAAe,IAAK,QAAQ,CAAE,EAC5C,CAAC,OAAQ,CAAE,EAAG,2DAA4D,IAAK,QAAQ,CAAE,CAC3F,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e}from"./index-
|
|
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.
|
|
@@ -9,4 +9,4 @@ import{n as e}from"./index-O0BQoyzo.js";/**
|
|
|
9
9
|
* This source code is licensed under the ISC license.
|
|
10
10
|
* See the LICENSE file in the root directory of this source tree.
|
|
11
11
|
*/const y=e("Eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);export{c as E,y as a};
|
|
12
|
-
//# sourceMappingURL=eye-
|
|
12
|
+
//# sourceMappingURL=eye-sY6WZb7D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eye-
|
|
1
|
+
{"version":3,"file":"eye-sY6WZb7D.js","sources":["../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../node_modules/lucide-react/dist/esm/icons/eye.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 EyeOff = createLucideIcon(\"EyeOff\", [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\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 Eye = createLucideIcon(\"Eye\", [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n"],"names":["EyeOff","createLucideIcon","Eye"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,iGACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,uCAAwC,IAAK,QAAQ,CAAE,EACrE,CACE,OACA,CACE,EAAG,+FACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC,EC1BD;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACC,EAAMD,EAAiB,MAAO,CAClC,CACE,OACA,CACE,EAAG,wGACH,IAAK,QACX,CACA,EACE,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CAC1D,CAAC","x_google_ignoreList":[0,1]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as Q,e as Y,j as e,k as D,B as b,L as E,I as J,S as W,f as X,g as Z,h as ee,i as k,l as p,m as T}from"./index-
|
|
2
|
-
//# sourceMappingURL=facts-
|
|
1
|
+
import{u as Q,e as Y,j as e,k as D,B as b,L as E,I as J,S as W,f as X,g as Z,h as ee,i as k,l as p,m as T}from"./index-DEWFfW_Z.js";import{r}from"./react-DlP5eolq.js";import{D as te}from"./data-table-DswkWUfG.js";import{E as B}from"./empty-state-D9Hi0Atm.js";import{P as se}from"./pagination-BAKRGKa9.js";import{C as M}from"./confirm-dialog-DlUsSur3.js";import{a as ae,b as ne,c as ce}from"./use-memory-BYEjVWbU.js";import{T as A}from"./trash-2-CA0cLpnU.js";import{B as R}from"./brain-B7HtSOQU.js";import{L as re}from"./loader-circle-Bbw4pEyE.js";import{R as ie}from"./refresh-ccw-uNKeBeRl.js";import{S as le}from"./search-i1tP2maJ.js";import"./table-BbAOSyc8.js";import"./arrow-up-BOADc9ce.js";import"./arrow-down-SLWKqtDc.js";import"./chevron-left-uSfPn636.js";import"./chevron-right-CtelqacW.js";import"./dialog-Ceo4YuXy.js";import"./x-D1iSuoqg.js";import"./useQuery-CY2iazjN.js";const oe=["fact","preference","goal","history","profile"],me=[25,50,100],F=50,de=300;function Be(){const{t:s}=Q(["memory","common"]),[n,L]=Y(),c=n.get("user")??"",i=n.get("q")??"",m=n.get("cat")??null,d=Math.max(1,Number(n.get("page"))||1),l=Number(n.get("per_page"))||F,[f,I]=r.useState(i);r.useEffect(()=>{if(f===i)return;const t=window.setTimeout(()=>h({q:f||null}),de);return()=>window.clearTimeout(t)},[f]);const q=r.useMemo(()=>({user_key:c,...i?{query:i}:{},...m?{category:m}:{},limit:l,offset:(d-1)*l}),[c,i,m,d,l]),{data:S,isLoading:z,isFetching:C,refetch:U}=ae(q,{enabled:!!c}),_=S?.facts??[],P=S?.total??0,G=Math.max(1,Math.ceil(P/l)),[u,g]=r.useState(new Set);r.useEffect(()=>{g(new Set)},[c,i,m,d,l]);const j=ne(),x=ce(),[y,v]=r.useState(null),[V,O]=r.useState(!1);function h(t){const a=new URLSearchParams(n);for(const[o,w]of Object.entries(t))w==null||w===""?a.delete(o):a.set(o,w);Object.keys(t).some(o=>o!=="page")&&a.delete("page"),L(a,{replace:!1})}async function $(){if(!(y==null||!c))try{await j.mutateAsync({id:y,user_key:c}),p.success(s("facts.toast.deletedOne"))}catch(t){const{message:a}=T(t,s);throw p.error(a),t}}async function H(){if(!c||u.size===0)return;const t=Array.from(u).map(Number).filter(Number.isFinite);try{const a=await x.mutateAsync({user_key:c,body:{ids:t}});p.success(s("facts.toast.deletedMany",{count:a.deleted})),g(new Set)}catch(a){const{message:o}=T(a,s);throw p.error(o),a}}const K=r.useMemo(()=>[{id:"id",header:s("facts.col.id"),cell:t=>e.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",t.id]}),headClassName:"w-16"},{id:"what",header:s("facts.col.what"),cell:t=>e.jsx("span",{className:"line-clamp-2 text-text",children:t.what}),asCardTitle:!0},{id:"category",header:s("facts.col.category"),cell:t=>e.jsx(D,{variant:"outline",children:s(`facts.category.${t.category}`,{defaultValue:t.category})}),headClassName:"w-28"},{id:"confidence",header:s("facts.col.confidence"),cell:t=>e.jsx("span",{className:"tabular-nums text-text-dim",children:t.confidence.toFixed(2)}),headClassName:"w-24",hideOnMobile:!0},{id:"source",header:s("facts.col.source"),cell:t=>e.jsx("span",{className:"text-text-dim text-xs",children:t.source}),headClassName:"w-28",hideOnMobile:!0},{id:"createdAt",header:s("facts.col.createdAt"),cell:t=>e.jsx("span",{className:"text-text-dim",children:fe(t.created_at)}),headClassName:"w-32",hideOnMobile:!0},{id:"actions",header:"",cell:t=>e.jsx("div",{className:"flex justify-end",children:e.jsxs(b,{variant:"ghost",size:"sm",onClick:a=>{a.stopPropagation(),v(t.id)},disabled:j.isPending||x.isPending,"aria-label":s("facts.action.delete"),children:[e.jsx(A,{className:"h-3 w-3"}),e.jsx("span",{className:"sr-only sm:not-sr-only sm:ml-1",children:s("facts.action.delete")})]})}),headClassName:"w-24"}],[s,j.isPending,x.isPending]);if(!c)return e.jsx("div",{className:"mx-auto max-w-3xl",children:e.jsx(B,{icon:e.jsx(R,{}),title:s("noUserSelected.title"),description:s("noUserSelected.description")})});const N=u.size;return e.jsxs("div",{className:"mx-auto flex max-w-7xl 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("facts.title")}),e.jsxs(b,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>U(),disabled:C,"aria-label":s("actions.refresh",{ns:"common"}),children:[C?e.jsx(re,{className:"h-4 w-4 animate-spin"}):e.jsx(ie,{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("subtitle")})]}),e.jsxs("div",{className:"flex flex-wrap items-end gap-2",children:[e.jsxs("div",{className:"relative flex-1 min-w-[200px] max-w-md",children:[e.jsx(E,{htmlFor:"search",className:"text-xs text-text-dim",children:s("facts.filter.search")}),e.jsx(le,{className:"pointer-events-none absolute left-2 bottom-2 h-4 w-4 text-text-muted"}),e.jsx(J,{id:"search",value:f,onChange:t=>I(t.target.value),className:"pl-7 mt-1"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(E,{htmlFor:"category",className:"text-xs text-text-dim",children:s("facts.filter.category")}),e.jsxs(W,{value:m??"__any__",onValueChange:t=>h({cat:t==="__any__"?null:t}),children:[e.jsx(X,{id:"category",className:"w-[140px]",children:e.jsx(Z,{})}),e.jsxs(ee,{children:[e.jsx(k,{value:"__any__",children:s("facts.filter.categoryAny")}),oe.map(t=>e.jsx(k,{value:t,children:s(`facts.category.${t}`)},t))]})]})]}),N>0&&e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[e.jsx(D,{variant:"secondary",children:s("facts.batch.selected",{count:N})}),e.jsxs(b,{variant:"destructive",size:"sm",onClick:()=>O(!0),disabled:x.isPending,children:[e.jsx(A,{className:"h-4 w-4"}),s("facts.batch.deleteSelected")]})]})]}),e.jsx(te,{columns:K,rows:_,getRowId:t=>String(t.id),loading:z,selection:u,onSelectionChange:g,emptyState:e.jsx(B,{icon:e.jsx(R,{}),title:s("facts.empty.title"),description:s("facts.empty.description")})}),(_.length>0||d>1)&&e.jsx(se,{page:d,totalPages:G,totalRows:P,perPage:l,perPageOptions:me,onPageChange:t=>h({page:t===1?null:String(t)}),onPerPageChange:t=>h({per_page:t===F?null:String(t)})}),e.jsx(M,{open:y!=null,onOpenChange:t=>{t||v(null)},title:s("facts.action.confirmDelete"),description:s("facts.action.confirmDeleteDesc"),intent:"danger",confirmLabel:s("facts.action.delete"),onConfirm:$}),e.jsx(M,{open:V,onOpenChange:O,title:s("facts.batch.confirmDelete",{count:N}),description:s("facts.batch.confirmDeleteDesc"),intent:"danger",confirmLabel:s("facts.batch.deleteSelected"),onConfirm:H})]})}function fe(s){try{const n=new Date(s);return Number.isNaN(n.getTime())?String(s):n.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return String(s)}}export{Be as default};
|
|
2
|
+
//# sourceMappingURL=facts-B7bGGwvi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facts-CGaLWhzi.js","sources":["../../src/routes/memory/facts.tsx"],"sourcesContent":["/**\n * /memory/facts — list / search / delete the user's facts.\n *\n * Reads `?user=` from the URL (the layout writes it). Without a\n * user_key the route shows a friendly empty state pointing at the\n * picker — no query fires until a user is chosen.\n *\n * Search + category filter live in URL params so deep-link sharing\n * works (\"show me john's goals matching tax\"). The free-text input\n * is local-only with a 300ms debounce, same pattern as /memos, so\n * the FTS5 layer isn't hit on every keystroke.\n *\n * Single-row delete via the per-row Delete button; batch delete via\n * checkbox selection + the bulk-delete action bar. Both route\n * through ConfirmDialog.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Brain, Loader2, RefreshCcw, Search, Trash2 } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { Pagination } from '@/components/common/pagination'\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 Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useMemoryFacts,\n useDeleteFactById,\n useBulkDeleteFacts,\n} from '@/hooks/use-memory'\nimport { describeError } from '@/lib/api/errors'\nimport type { Fact, FactCategory, ListMemoryFactsQuery } from '@/types/api'\n\nconst CATEGORY_OPTIONS: FactCategory[] = ['fact', 'preference', 'goal', 'history', 'profile']\nconst PER_PAGE_OPTIONS = [25, 50, 100]\nconst DEFAULT_PER_PAGE = 50\nconst SEARCH_DEBOUNCE_MS = 300\n\nexport default function MemoryFactsRoute(): JSX.Element {\n const { t } = useTranslation(['memory', 'common'])\n const [params, setParams] = useSearchParams()\n\n const userKey = params.get('user') ?? ''\n const q = params.get('q') ?? ''\n const cat = (params.get('cat') as FactCategory | null) ?? null\n const page = Math.max(1, Number(params.get('page')) || 1)\n const perPage = Number(params.get('per_page')) || DEFAULT_PER_PAGE\n\n const [qDraft, setQDraft] = useState(q)\n useEffect(() => {\n if (qDraft === q) return\n const timer = window.setTimeout(() => patchParams({ q: qDraft || null }), SEARCH_DEBOUNCE_MS)\n return () => window.clearTimeout(timer)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [qDraft])\n\n const query: ListMemoryFactsQuery = useMemo(\n () => ({\n user_key: userKey,\n ...(q ? { query: q } : {}),\n ...(cat ? { category: cat } : {}),\n limit: perPage,\n offset: (page - 1) * perPage,\n }),\n [userKey, q, cat, page, perPage],\n )\n\n const { data, isLoading, isFetching, refetch } = useMemoryFacts(query, { enabled: Boolean(userKey) })\n const facts = data?.facts ?? []\n const total = data?.total ?? 0\n const totalPages = Math.max(1, Math.ceil(total / perPage))\n\n // Selection state for the bulk delete bar.\n const [selection, setSelection] = useState<Set<string>>(new Set())\n useEffect(() => { setSelection(new Set()) }, [userKey, q, cat, page, perPage])\n\n const deleteOne = useDeleteFactById()\n const bulkDelete = useBulkDeleteFacts()\n\n const [confirmOneId, setConfirmOneId] = useState<number | null>(null)\n const [confirmBulk, setConfirmBulk] = useState(false)\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 || v === '') next.delete(k)\n else next.set(k, v)\n }\n // Reset to page 1 on any filter mutation.\n if (Object.keys(patch).some((k) => k !== 'page')) next.delete('page')\n setParams(next, { replace: false })\n }\n\n async function onConfirmDeleteOne(): Promise<void> {\n if (confirmOneId == null || !userKey) return\n try {\n await deleteOne.mutateAsync({ id: confirmOneId, user_key: userKey })\n toast.success(t('facts.toast.deletedOne'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onConfirmBulk(): Promise<void> {\n if (!userKey || selection.size === 0) return\n const ids = Array.from(selection).map(Number).filter(Number.isFinite)\n try {\n const r = await bulkDelete.mutateAsync({ user_key: userKey, body: { ids } })\n toast.success(t('facts.toast.deletedMany', { count: r.deleted }))\n setSelection(new Set())\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n const columns: DataTableColumn<Fact>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('facts.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'what',\n header: t('facts.col.what'),\n cell: (r) => <span className=\"line-clamp-2 text-text\">{r.what}</span>,\n asCardTitle: true,\n },\n {\n id: 'category',\n header: t('facts.col.category'),\n cell: (r) => (\n <Badge variant=\"outline\">\n {t(`facts.category.${r.category}`, { defaultValue: r.category })}\n </Badge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'confidence',\n header: t('facts.col.confidence'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">{r.confidence.toFixed(2)}</span>,\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'source',\n header: t('facts.col.source'),\n cell: (r) => <span className=\"text-text-dim text-xs\">{r.source}</span>,\n headClassName: 'w-28',\n hideOnMobile: true,\n },\n {\n id: 'createdAt',\n header: t('facts.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatEpoch(r.created_at)}</span>,\n headClassName: 'w-32',\n hideOnMobile: true,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) => (\n <div className=\"flex justify-end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmOneId(r.id)\n }}\n disabled={deleteOne.isPending || bulkDelete.isPending}\n aria-label={t('facts.action.delete')}\n >\n <Trash2 className=\"h-3 w-3\" />\n <span className=\"sr-only sm:not-sr-only sm:ml-1\">{t('facts.action.delete')}</span>\n </Button>\n </div>\n ),\n headClassName: 'w-24',\n },\n ],\n [t, deleteOne.isPending, bulkDelete.isPending],\n )\n\n if (!userKey) {\n return (\n <div className=\"mx-auto max-w-3xl\">\n <EmptyState\n icon={<Brain />}\n title={t('noUserSelected.title')}\n description={t('noUserSelected.description')}\n />\n </div>\n )\n }\n\n const selectedCount = selection.size\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('facts.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 <p className=\"text-sm text-text-dim\">{t('subtitle')}</p>\n </header>\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"relative flex-1 min-w-[200px] max-w-md\">\n <Label htmlFor=\"search\" className=\"text-xs text-text-dim\">\n {t('facts.filter.search')}\n </Label>\n <Search className=\"pointer-events-none absolute left-2 bottom-2 h-4 w-4 text-text-muted\" />\n <Input\n id=\"search\"\n value={qDraft}\n onChange={(e) => setQDraft(e.target.value)}\n className=\"pl-7 mt-1\"\n />\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"category\" className=\"text-xs text-text-dim\">\n {t('facts.filter.category')}\n </Label>\n <Select\n value={cat ?? '__any__'}\n onValueChange={(v) => patchParams({ cat: v === '__any__' ? null : v })}\n >\n <SelectTrigger id=\"category\" className=\"w-[140px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__any__\">{t('facts.filter.categoryAny')}</SelectItem>\n {CATEGORY_OPTIONS.map((c) => (\n <SelectItem key={c} value={c}>\n {t(`facts.category.${c}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {selectedCount > 0 && (\n <div className=\"ml-auto flex items-center gap-2\">\n <Badge variant=\"secondary\">\n {t('facts.batch.selected', { count: selectedCount })}\n </Badge>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => setConfirmBulk(true)}\n disabled={bulkDelete.isPending}\n >\n <Trash2 className=\"h-4 w-4\" />\n {t('facts.batch.deleteSelected')}\n </Button>\n </div>\n )}\n </div>\n\n <DataTable\n columns={columns}\n rows={facts}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n selection={selection}\n onSelectionChange={setSelection}\n emptyState={\n <EmptyState\n icon={<Brain />}\n title={t('facts.empty.title')}\n description={t('facts.empty.description')}\n />\n }\n />\n\n {(facts.length > 0 || page > 1) && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalRows={total}\n perPage={perPage}\n perPageOptions={PER_PAGE_OPTIONS}\n onPageChange={(p) => patchParams({ page: p === 1 ? null : String(p) })}\n onPerPageChange={(pp) => patchParams({ per_page: pp === DEFAULT_PER_PAGE ? null : String(pp) })}\n />\n )}\n\n <ConfirmDialog\n open={confirmOneId != null}\n onOpenChange={(open) => { if (!open) setConfirmOneId(null) }}\n title={t('facts.action.confirmDelete')}\n description={t('facts.action.confirmDeleteDesc')}\n intent=\"danger\"\n confirmLabel={t('facts.action.delete')}\n onConfirm={onConfirmDeleteOne}\n />\n\n <ConfirmDialog\n open={confirmBulk}\n onOpenChange={setConfirmBulk}\n title={t('facts.batch.confirmDelete', { count: selectedCount })}\n description={t('facts.batch.confirmDeleteDesc')}\n intent=\"danger\"\n confirmLabel={t('facts.batch.deleteSelected')}\n onConfirm={onConfirmBulk}\n />\n </div>\n )\n}\n\n/** Format an epoch-ms number as a short locale string. */\nfunction formatEpoch(ms: number): string {\n try {\n const d = new Date(ms)\n if (Number.isNaN(d.getTime())) return String(ms)\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return String(ms)\n }\n}\n"],"names":["CATEGORY_OPTIONS","PER_PAGE_OPTIONS","DEFAULT_PER_PAGE","SEARCH_DEBOUNCE_MS","MemoryFactsRoute","t","useTranslation","params","setParams","useSearchParams","userKey","q","cat","page","perPage","qDraft","setQDraft","useState","useEffect","timer","patchParams","query","useMemo","data","isLoading","isFetching","refetch","useMemoryFacts","facts","total","totalPages","selection","setSelection","deleteOne","useDeleteFactById","bulkDelete","useBulkDeleteFacts","confirmOneId","setConfirmOneId","confirmBulk","setConfirmBulk","patch","next","k","v","onConfirmDeleteOne","toast","err","message","describeError","onConfirmBulk","ids","r","columns","jsxs","jsx","Badge","formatEpoch","Button","e","Trash2","EmptyState","Brain","selectedCount","Loader2","RefreshCcw","Label","Search","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","c","DataTable","Pagination","p","pp","ConfirmDialog","open","ms","d"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"facts-B7bGGwvi.js","sources":["../../src/routes/memory/facts.tsx"],"sourcesContent":["/**\n * /memory/facts — list / search / delete the user's facts.\n *\n * Reads `?user=` from the URL (the layout writes it). Without a\n * user_key the route shows a friendly empty state pointing at the\n * picker — no query fires until a user is chosen.\n *\n * Search + category filter live in URL params so deep-link sharing\n * works (\"show me john's goals matching tax\"). The free-text input\n * is local-only with a 300ms debounce, same pattern as /memos, so\n * the FTS5 layer isn't hit on every keystroke.\n *\n * Single-row delete via the per-row Delete button; batch delete via\n * checkbox selection + the bulk-delete action bar. Both route\n * through ConfirmDialog.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Brain, Loader2, RefreshCcw, Search, Trash2 } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { Pagination } from '@/components/common/pagination'\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 Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useMemoryFacts,\n useDeleteFactById,\n useBulkDeleteFacts,\n} from '@/hooks/use-memory'\nimport { describeError } from '@/lib/api/errors'\nimport type { Fact, FactCategory, ListMemoryFactsQuery } from '@/types/api'\n\nconst CATEGORY_OPTIONS: FactCategory[] = ['fact', 'preference', 'goal', 'history', 'profile']\nconst PER_PAGE_OPTIONS = [25, 50, 100]\nconst DEFAULT_PER_PAGE = 50\nconst SEARCH_DEBOUNCE_MS = 300\n\nexport default function MemoryFactsRoute(): JSX.Element {\n const { t } = useTranslation(['memory', 'common'])\n const [params, setParams] = useSearchParams()\n\n const userKey = params.get('user') ?? ''\n const q = params.get('q') ?? ''\n const cat = (params.get('cat') as FactCategory | null) ?? null\n const page = Math.max(1, Number(params.get('page')) || 1)\n const perPage = Number(params.get('per_page')) || DEFAULT_PER_PAGE\n\n const [qDraft, setQDraft] = useState(q)\n useEffect(() => {\n if (qDraft === q) return\n const timer = window.setTimeout(() => patchParams({ q: qDraft || null }), SEARCH_DEBOUNCE_MS)\n return () => window.clearTimeout(timer)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [qDraft])\n\n const query: ListMemoryFactsQuery = useMemo(\n () => ({\n user_key: userKey,\n ...(q ? { query: q } : {}),\n ...(cat ? { category: cat } : {}),\n limit: perPage,\n offset: (page - 1) * perPage,\n }),\n [userKey, q, cat, page, perPage],\n )\n\n const { data, isLoading, isFetching, refetch } = useMemoryFacts(query, { enabled: Boolean(userKey) })\n const facts = data?.facts ?? []\n const total = data?.total ?? 0\n const totalPages = Math.max(1, Math.ceil(total / perPage))\n\n // Selection state for the bulk delete bar.\n const [selection, setSelection] = useState<Set<string>>(new Set())\n useEffect(() => { setSelection(new Set()) }, [userKey, q, cat, page, perPage])\n\n const deleteOne = useDeleteFactById()\n const bulkDelete = useBulkDeleteFacts()\n\n const [confirmOneId, setConfirmOneId] = useState<number | null>(null)\n const [confirmBulk, setConfirmBulk] = useState(false)\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 || v === '') next.delete(k)\n else next.set(k, v)\n }\n // Reset to page 1 on any filter mutation.\n if (Object.keys(patch).some((k) => k !== 'page')) next.delete('page')\n setParams(next, { replace: false })\n }\n\n async function onConfirmDeleteOne(): Promise<void> {\n if (confirmOneId == null || !userKey) return\n try {\n await deleteOne.mutateAsync({ id: confirmOneId, user_key: userKey })\n toast.success(t('facts.toast.deletedOne'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onConfirmBulk(): Promise<void> {\n if (!userKey || selection.size === 0) return\n const ids = Array.from(selection).map(Number).filter(Number.isFinite)\n try {\n const r = await bulkDelete.mutateAsync({ user_key: userKey, body: { ids } })\n toast.success(t('facts.toast.deletedMany', { count: r.deleted }))\n setSelection(new Set())\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n const columns: DataTableColumn<Fact>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('facts.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'what',\n header: t('facts.col.what'),\n cell: (r) => <span className=\"line-clamp-2 text-text\">{r.what}</span>,\n asCardTitle: true,\n },\n {\n id: 'category',\n header: t('facts.col.category'),\n cell: (r) => (\n <Badge variant=\"outline\">\n {t(`facts.category.${r.category}`, { defaultValue: r.category })}\n </Badge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'confidence',\n header: t('facts.col.confidence'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">{r.confidence.toFixed(2)}</span>,\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'source',\n header: t('facts.col.source'),\n cell: (r) => <span className=\"text-text-dim text-xs\">{r.source}</span>,\n headClassName: 'w-28',\n hideOnMobile: true,\n },\n {\n id: 'createdAt',\n header: t('facts.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatEpoch(r.created_at)}</span>,\n headClassName: 'w-32',\n hideOnMobile: true,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) => (\n <div className=\"flex justify-end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmOneId(r.id)\n }}\n disabled={deleteOne.isPending || bulkDelete.isPending}\n aria-label={t('facts.action.delete')}\n >\n <Trash2 className=\"h-3 w-3\" />\n <span className=\"sr-only sm:not-sr-only sm:ml-1\">{t('facts.action.delete')}</span>\n </Button>\n </div>\n ),\n headClassName: 'w-24',\n },\n ],\n [t, deleteOne.isPending, bulkDelete.isPending],\n )\n\n if (!userKey) {\n return (\n <div className=\"mx-auto max-w-3xl\">\n <EmptyState\n icon={<Brain />}\n title={t('noUserSelected.title')}\n description={t('noUserSelected.description')}\n />\n </div>\n )\n }\n\n const selectedCount = selection.size\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('facts.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 <p className=\"text-sm text-text-dim\">{t('subtitle')}</p>\n </header>\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"relative flex-1 min-w-[200px] max-w-md\">\n <Label htmlFor=\"search\" className=\"text-xs text-text-dim\">\n {t('facts.filter.search')}\n </Label>\n <Search className=\"pointer-events-none absolute left-2 bottom-2 h-4 w-4 text-text-muted\" />\n <Input\n id=\"search\"\n value={qDraft}\n onChange={(e) => setQDraft(e.target.value)}\n className=\"pl-7 mt-1\"\n />\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"category\" className=\"text-xs text-text-dim\">\n {t('facts.filter.category')}\n </Label>\n <Select\n value={cat ?? '__any__'}\n onValueChange={(v) => patchParams({ cat: v === '__any__' ? null : v })}\n >\n <SelectTrigger id=\"category\" className=\"w-[140px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__any__\">{t('facts.filter.categoryAny')}</SelectItem>\n {CATEGORY_OPTIONS.map((c) => (\n <SelectItem key={c} value={c}>\n {t(`facts.category.${c}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {selectedCount > 0 && (\n <div className=\"ml-auto flex items-center gap-2\">\n <Badge variant=\"secondary\">\n {t('facts.batch.selected', { count: selectedCount })}\n </Badge>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => setConfirmBulk(true)}\n disabled={bulkDelete.isPending}\n >\n <Trash2 className=\"h-4 w-4\" />\n {t('facts.batch.deleteSelected')}\n </Button>\n </div>\n )}\n </div>\n\n <DataTable\n columns={columns}\n rows={facts}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n selection={selection}\n onSelectionChange={setSelection}\n emptyState={\n <EmptyState\n icon={<Brain />}\n title={t('facts.empty.title')}\n description={t('facts.empty.description')}\n />\n }\n />\n\n {(facts.length > 0 || page > 1) && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalRows={total}\n perPage={perPage}\n perPageOptions={PER_PAGE_OPTIONS}\n onPageChange={(p) => patchParams({ page: p === 1 ? null : String(p) })}\n onPerPageChange={(pp) => patchParams({ per_page: pp === DEFAULT_PER_PAGE ? null : String(pp) })}\n />\n )}\n\n <ConfirmDialog\n open={confirmOneId != null}\n onOpenChange={(open) => { if (!open) setConfirmOneId(null) }}\n title={t('facts.action.confirmDelete')}\n description={t('facts.action.confirmDeleteDesc')}\n intent=\"danger\"\n confirmLabel={t('facts.action.delete')}\n onConfirm={onConfirmDeleteOne}\n />\n\n <ConfirmDialog\n open={confirmBulk}\n onOpenChange={setConfirmBulk}\n title={t('facts.batch.confirmDelete', { count: selectedCount })}\n description={t('facts.batch.confirmDeleteDesc')}\n intent=\"danger\"\n confirmLabel={t('facts.batch.deleteSelected')}\n onConfirm={onConfirmBulk}\n />\n </div>\n )\n}\n\n/** Format an epoch-ms number as a short locale string. */\nfunction formatEpoch(ms: number): string {\n try {\n const d = new Date(ms)\n if (Number.isNaN(d.getTime())) return String(ms)\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return String(ms)\n }\n}\n"],"names":["CATEGORY_OPTIONS","PER_PAGE_OPTIONS","DEFAULT_PER_PAGE","SEARCH_DEBOUNCE_MS","MemoryFactsRoute","t","useTranslation","params","setParams","useSearchParams","userKey","q","cat","page","perPage","qDraft","setQDraft","useState","useEffect","timer","patchParams","query","useMemo","data","isLoading","isFetching","refetch","useMemoryFacts","facts","total","totalPages","selection","setSelection","deleteOne","useDeleteFactById","bulkDelete","useBulkDeleteFacts","confirmOneId","setConfirmOneId","confirmBulk","setConfirmBulk","patch","next","k","v","onConfirmDeleteOne","toast","err","message","describeError","onConfirmBulk","ids","r","columns","jsxs","jsx","Badge","formatEpoch","Button","e","Trash2","EmptyState","Brain","selectedCount","Loader2","RefreshCcw","Label","Search","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","c","DataTable","Pagination","p","pp","ConfirmDialog","open","ms","d"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as h,u as g,j as e,k as p,B as d,l as j}from"./index-
|
|
1
|
+
import{n as h,u as g,j as e,k as p,B as d,l as j}from"./index-DEWFfW_Z.js";import{r as u}from"./react-DlP5eolq.js";import{T as N,a as k,b as m,c as i,d as v,e as t}from"./table-BbAOSyc8.js";import{b as w,c as C}from"./use-background-tasks-B64YjlA8.js";import{L as T}from"./loader-circle-Bbw4pEyE.js";import{R as L}from"./refresh-ccw-uNKeBeRl.js";import{C as M}from"./circle-check-8dbL-u7O.js";import{C as S}from"./circle-x-rUxzIz5P.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.
|
|
@@ -14,4 +14,4 @@ import{n as h,u as g,j as e,k as p,B as d,l as j}from"./index-O0BQoyzo.js";impor
|
|
|
14
14
|
* This source code is licensed under the ISC license.
|
|
15
15
|
* See the LICENSE file in the root directory of this source tree.
|
|
16
16
|
*/const P=h("Target",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"6",key:"1vlfrh"}],["circle",{cx:"12",cy:"12",r:"2",key:"1c9p78"}]]);function Q(){const{t:s}=g(["tasks","common"]),r=w(),o=C(),[y,f]=u.useState(null);async function n(a,l){try{await o.mutateAsync({id:a.id,status:l}),j.success(s("goals.statusUpdated",{status:l}))}catch(c){j.error(c?.message??String(c))}}const x=r.data?.goals??[];return e.jsxs("div",{className:"mx-auto flex max-w-6xl flex-col gap-4 p-4",children:[e.jsxs("header",{className:"flex items-center gap-3",children:[e.jsx(P,{className:"h-5 w-5 text-text-dim"}),e.jsx("h1",{className:"text-xl font-semibold",children:s("goals.title")}),e.jsx(p,{variant:"info",children:x.length}),e.jsxs(d,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>void r.refetch(),disabled:r.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[r.isFetching?e.jsx(T,{className:"h-4 w-4 animate-spin"}):e.jsx(L,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("goals.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:s("goals.subtitle")}),r.isLoading?e.jsx("div",{className:"h-48 rounded-md bg-surface-2 animate-pulse"}):x.length===0?e.jsx(A,{}):e.jsx("section",{className:"rounded-md border border-border bg-surface",children:e.jsxs(N,{children:[e.jsx(k,{children:e.jsxs(m,{children:[e.jsx(i,{className:"w-12",children:s("goals.col.id")}),e.jsx(i,{children:s("goals.col.thread")}),e.jsx(i,{children:s("goals.col.title")}),e.jsx(i,{children:s("goals.col.progress")}),e.jsx(i,{children:s("goals.col.updated")}),e.jsx(i,{children:s("goals.col.actions")})]})}),e.jsx(v,{children:x.map(a=>{const l=y===a.id;return e.jsxs(u.Fragment,{children:[e.jsxs(m,{children:[e.jsx(t,{className:"font-mono text-xs",children:a.id}),e.jsxs(t,{className:"font-mono text-[11px]",children:[a.platform,":",a.threadId]}),e.jsx(t,{children:e.jsx(d,{variant:"ghost",size:"sm",className:"-ml-2 text-left",onClick:()=>f(l?null:a.id),title:s(l?"goals.hideBody":"goals.showBody"),children:a.title})}),e.jsx(t,{children:e.jsx(p,{variant:"outline",children:a.progressCount})}),e.jsx(t,{className:"text-[11px] text-text-dim",children:a.updatedAt}),e.jsxs(t,{className:"flex flex-wrap gap-1",children:[e.jsx(d,{variant:"ghost",size:"sm",title:s("goals.pause"),onClick:()=>void n(a,"paused"),disabled:o.isPending,children:e.jsx(B,{className:"h-4 w-4"})}),e.jsx(d,{variant:"ghost",size:"sm",title:s("goals.complete"),onClick:()=>void n(a,"completed"),disabled:o.isPending,children:e.jsx(M,{className:"h-4 w-4 text-success"})}),e.jsx(d,{variant:"ghost",size:"sm",title:s("goals.cancel"),onClick:()=>void n(a,"cancelled"),disabled:o.isPending,className:"text-danger hover:text-danger",children:e.jsx(S,{className:"h-4 w-4"})})]})]}),l&&e.jsxs(m,{children:[e.jsx(t,{}),e.jsx(t,{colSpan:5,children:e.jsxs("div",{className:"space-y-2 rounded bg-surface-2 p-3 text-xs",children:[a.body&&e.jsxs("div",{children:[e.jsx("div",{className:"text-text-dim",children:s("goals.body")}),e.jsx("pre",{className:"mt-1 whitespace-pre-wrap break-words",children:a.body})]}),a.progressLog.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"text-text-dim",children:s("goals.recentProgress",{count:a.progressLog.length})}),e.jsx("ul",{className:"mt-1 space-y-1",children:a.progressLog.slice().reverse().map((c,b)=>e.jsxs("li",{className:"font-mono text-[11px]",children:[e.jsxs("span",{className:"text-text-dim",children:[c.ts.slice(0,19)," (",c.by,")"]})," ",c.text]},b))})]}),e.jsxs("div",{className:"text-[11px] text-text-dim",children:[s("goals.created",{at:a.createdAt}),a.closedAt?` · ${s("goals.closed",{at:a.closedAt})}`:""]})]})})]})]},a.id)})})]})})]})}function A(){const{t:s}=g("tasks");return e.jsxs("section",{className:"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim",children:[s("goals.empty"),e.jsx("div",{className:"mt-2",children:e.jsx(z,{className:"mx-auto h-8 w-8 opacity-30"})})]})}export{Q as default};
|
|
17
|
-
//# sourceMappingURL=goals-
|
|
17
|
+
//# sourceMappingURL=goals-BfQbsvZv.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goals-C-dJANmn.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-dashed.js","../../node_modules/lucide-react/dist/esm/icons/circle-pause.js","../../node_modules/lucide-react/dist/esm/icons/target.js","../../src/routes/tasks/goals.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 CircleDashed = createLucideIcon(\"CircleDashed\", [\n [\"path\", { d: \"M10.1 2.182a10 10 0 0 1 3.8 0\", key: \"5ilxe3\" }],\n [\"path\", { d: \"M13.9 21.818a10 10 0 0 1-3.8 0\", key: \"11zvb9\" }],\n [\"path\", { d: \"M17.609 3.721a10 10 0 0 1 2.69 2.7\", key: \"1iw5b2\" }],\n [\"path\", { d: \"M2.182 13.9a10 10 0 0 1 0-3.8\", key: \"c0bmvh\" }],\n [\"path\", { d: \"M20.279 17.609a10 10 0 0 1-2.7 2.69\", key: \"1ruxm7\" }],\n [\"path\", { d: \"M21.818 10.1a10 10 0 0 1 0 3.8\", key: \"qkgqxc\" }],\n [\"path\", { d: \"M3.721 6.391a10 10 0 0 1 2.7-2.69\", key: \"1mcia2\" }],\n [\"path\", { d: \"M6.391 20.279a10 10 0 0 1-2.69-2.7\", key: \"1fvljs\" }]\n]);\n\nexport { CircleDashed as default };\n//# sourceMappingURL=circle-dashed.js.map\n","/**\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 CirclePause = createLucideIcon(\"CirclePause\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"15\", y2: \"9\", key: \"c1nkhi\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"15\", y2: \"9\", key: \"h65svq\" }]\n]);\n\nexport { CirclePause as default };\n//# sourceMappingURL=circle-pause.js.map\n","/**\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 Target = createLucideIcon(\"Target\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"6\", key: \"1vlfrh\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"2\", key: \"1c9p78\" }]\n]);\n\nexport { Target as default };\n//# sourceMappingURL=target.js.map\n","/**\n * /tasks/goals — admin overview of every ACTIVE goal (P1).\n */\n\nimport { Fragment, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { CheckCircle2, CircleDashed, Loader2, PauseCircle, RefreshCcw, Target, XCircle } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Table, TableBody, TableCell, TableHead, TableHeader, TableRow,\n} from '@/components/ui/table'\nimport {\n useGoalsList, useGoalUpdateStatus, type GoalRow,\n} from '@/hooks/use-background-tasks'\n\nexport default function TasksGoalsRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const listQuery = useGoalsList()\n const updateStatus = useGoalUpdateStatus()\n const [expandedId, setExpandedId] = useState<number | null>(null)\n\n async function onChangeStatus(g: GoalRow, status: GoalRow['status']): Promise<void> {\n try {\n await updateStatus.mutateAsync({ id: g.id, status })\n toast.success(t('goals.statusUpdated', { status }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n const rows = listQuery.data?.goals ?? []\n return (\n <div className=\"mx-auto flex max-w-6xl flex-col gap-4 p-4\">\n <header className=\"flex items-center gap-3\">\n <Target className=\"h-5 w-5 text-text-dim\" />\n <h1 className=\"text-xl font-semibold\">{t('goals.title')}</h1>\n <Badge variant=\"info\">{rows.length}</Badge>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => void listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('goals.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('goals.subtitle')}</p>\n\n {listQuery.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : rows.length === 0 ? (\n <EmptySection />\n ) : (\n <section className=\"rounded-md border border-border bg-surface\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-12\">{t('goals.col.id')}</TableHead>\n <TableHead>{t('goals.col.thread')}</TableHead>\n <TableHead>{t('goals.col.title')}</TableHead>\n <TableHead>{t('goals.col.progress')}</TableHead>\n <TableHead>{t('goals.col.updated')}</TableHead>\n <TableHead>{t('goals.col.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((g) => {\n const isExpanded = expandedId === g.id\n return (\n <Fragment key={g.id}>\n <TableRow>\n <TableCell className=\"font-mono text-xs\">{g.id}</TableCell>\n <TableCell className=\"font-mono text-[11px]\">{g.platform}:{g.threadId}</TableCell>\n <TableCell>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"-ml-2 text-left\"\n onClick={() => setExpandedId(isExpanded ? null : g.id)}\n title={isExpanded ? t('goals.hideBody') : t('goals.showBody')}\n >\n {g.title}\n </Button>\n </TableCell>\n <TableCell><Badge variant=\"outline\">{g.progressCount}</Badge></TableCell>\n <TableCell className=\"text-[11px] text-text-dim\">{g.updatedAt}</TableCell>\n <TableCell className=\"flex flex-wrap gap-1\">\n <Button\n variant=\"ghost\" size=\"sm\" title={t('goals.pause')}\n onClick={() => void onChangeStatus(g, 'paused')}\n disabled={updateStatus.isPending}\n >\n <PauseCircle className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\" title={t('goals.complete')}\n onClick={() => void onChangeStatus(g, 'completed')}\n disabled={updateStatus.isPending}\n >\n <CheckCircle2 className=\"h-4 w-4 text-success\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\" title={t('goals.cancel')}\n onClick={() => void onChangeStatus(g, 'cancelled')}\n disabled={updateStatus.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <XCircle className=\"h-4 w-4\" />\n </Button>\n </TableCell>\n </TableRow>\n {isExpanded && (\n <TableRow>\n <TableCell />\n <TableCell colSpan={5}>\n <div className=\"space-y-2 rounded bg-surface-2 p-3 text-xs\">\n {g.body && (\n <div>\n <div className=\"text-text-dim\">{t('goals.body')}</div>\n <pre className=\"mt-1 whitespace-pre-wrap break-words\">{g.body}</pre>\n </div>\n )}\n {g.progressLog.length > 0 && (\n <div>\n <div className=\"text-text-dim\">\n {t('goals.recentProgress', { count: g.progressLog.length })}\n </div>\n <ul className=\"mt-1 space-y-1\">\n {g.progressLog.slice().reverse().map((n, i) => (\n <li key={i} className=\"font-mono text-[11px]\">\n <span className=\"text-text-dim\">{n.ts.slice(0, 19)} ({n.by})</span> {n.text}\n </li>\n ))}\n </ul>\n </div>\n )}\n <div className=\"text-[11px] text-text-dim\">\n {t('goals.created', { at: g.createdAt })}\n {g.closedAt ? ` · ${t('goals.closed', { at: g.closedAt })}` : ''}\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n )\n })}\n </TableBody>\n </Table>\n </section>\n )}\n </div>\n )\n}\n\nfunction EmptySection(): JSX.Element {\n const { t } = useTranslation('tasks')\n return (\n <section className=\"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim\">\n {t('goals.empty')}\n <div className=\"mt-2\">\n <CircleDashed className=\"mx-auto h-8 w-8 opacity-30\" />\n </div>\n </section>\n )\n}\n"],"names":["CircleDashed","createLucideIcon","CirclePause","Target","TasksGoalsRoute","t","useTranslation","listQuery","useGoalsList","updateStatus","useGoalUpdateStatus","expandedId","setExpandedId","useState","onChangeStatus","g","status","toast","err","rows","jsxs","jsx","Badge","Button","Loader2","RefreshCcw","EmptySection","Table","TableHeader","TableRow","TableHead","TableBody","isExpanded","Fragment","TableCell","PauseCircle","CheckCircle2","XCircle","n","i"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
1
|
+
{"version":3,"file":"goals-BfQbsvZv.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-dashed.js","../../node_modules/lucide-react/dist/esm/icons/circle-pause.js","../../node_modules/lucide-react/dist/esm/icons/target.js","../../src/routes/tasks/goals.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 CircleDashed = createLucideIcon(\"CircleDashed\", [\n [\"path\", { d: \"M10.1 2.182a10 10 0 0 1 3.8 0\", key: \"5ilxe3\" }],\n [\"path\", { d: \"M13.9 21.818a10 10 0 0 1-3.8 0\", key: \"11zvb9\" }],\n [\"path\", { d: \"M17.609 3.721a10 10 0 0 1 2.69 2.7\", key: \"1iw5b2\" }],\n [\"path\", { d: \"M2.182 13.9a10 10 0 0 1 0-3.8\", key: \"c0bmvh\" }],\n [\"path\", { d: \"M20.279 17.609a10 10 0 0 1-2.7 2.69\", key: \"1ruxm7\" }],\n [\"path\", { d: \"M21.818 10.1a10 10 0 0 1 0 3.8\", key: \"qkgqxc\" }],\n [\"path\", { d: \"M3.721 6.391a10 10 0 0 1 2.7-2.69\", key: \"1mcia2\" }],\n [\"path\", { d: \"M6.391 20.279a10 10 0 0 1-2.69-2.7\", key: \"1fvljs\" }]\n]);\n\nexport { CircleDashed as default };\n//# sourceMappingURL=circle-dashed.js.map\n","/**\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 CirclePause = createLucideIcon(\"CirclePause\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"15\", y2: \"9\", key: \"c1nkhi\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"15\", y2: \"9\", key: \"h65svq\" }]\n]);\n\nexport { CirclePause as default };\n//# sourceMappingURL=circle-pause.js.map\n","/**\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 Target = createLucideIcon(\"Target\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"6\", key: \"1vlfrh\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"2\", key: \"1c9p78\" }]\n]);\n\nexport { Target as default };\n//# sourceMappingURL=target.js.map\n","/**\n * /tasks/goals — admin overview of every ACTIVE goal (P1).\n */\n\nimport { Fragment, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { CheckCircle2, CircleDashed, Loader2, PauseCircle, RefreshCcw, Target, XCircle } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Table, TableBody, TableCell, TableHead, TableHeader, TableRow,\n} from '@/components/ui/table'\nimport {\n useGoalsList, useGoalUpdateStatus, type GoalRow,\n} from '@/hooks/use-background-tasks'\n\nexport default function TasksGoalsRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const listQuery = useGoalsList()\n const updateStatus = useGoalUpdateStatus()\n const [expandedId, setExpandedId] = useState<number | null>(null)\n\n async function onChangeStatus(g: GoalRow, status: GoalRow['status']): Promise<void> {\n try {\n await updateStatus.mutateAsync({ id: g.id, status })\n toast.success(t('goals.statusUpdated', { status }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n const rows = listQuery.data?.goals ?? []\n return (\n <div className=\"mx-auto flex max-w-6xl flex-col gap-4 p-4\">\n <header className=\"flex items-center gap-3\">\n <Target className=\"h-5 w-5 text-text-dim\" />\n <h1 className=\"text-xl font-semibold\">{t('goals.title')}</h1>\n <Badge variant=\"info\">{rows.length}</Badge>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => void listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('goals.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('goals.subtitle')}</p>\n\n {listQuery.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : rows.length === 0 ? (\n <EmptySection />\n ) : (\n <section className=\"rounded-md border border-border bg-surface\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-12\">{t('goals.col.id')}</TableHead>\n <TableHead>{t('goals.col.thread')}</TableHead>\n <TableHead>{t('goals.col.title')}</TableHead>\n <TableHead>{t('goals.col.progress')}</TableHead>\n <TableHead>{t('goals.col.updated')}</TableHead>\n <TableHead>{t('goals.col.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((g) => {\n const isExpanded = expandedId === g.id\n return (\n <Fragment key={g.id}>\n <TableRow>\n <TableCell className=\"font-mono text-xs\">{g.id}</TableCell>\n <TableCell className=\"font-mono text-[11px]\">{g.platform}:{g.threadId}</TableCell>\n <TableCell>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"-ml-2 text-left\"\n onClick={() => setExpandedId(isExpanded ? null : g.id)}\n title={isExpanded ? t('goals.hideBody') : t('goals.showBody')}\n >\n {g.title}\n </Button>\n </TableCell>\n <TableCell><Badge variant=\"outline\">{g.progressCount}</Badge></TableCell>\n <TableCell className=\"text-[11px] text-text-dim\">{g.updatedAt}</TableCell>\n <TableCell className=\"flex flex-wrap gap-1\">\n <Button\n variant=\"ghost\" size=\"sm\" title={t('goals.pause')}\n onClick={() => void onChangeStatus(g, 'paused')}\n disabled={updateStatus.isPending}\n >\n <PauseCircle className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\" title={t('goals.complete')}\n onClick={() => void onChangeStatus(g, 'completed')}\n disabled={updateStatus.isPending}\n >\n <CheckCircle2 className=\"h-4 w-4 text-success\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\" title={t('goals.cancel')}\n onClick={() => void onChangeStatus(g, 'cancelled')}\n disabled={updateStatus.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <XCircle className=\"h-4 w-4\" />\n </Button>\n </TableCell>\n </TableRow>\n {isExpanded && (\n <TableRow>\n <TableCell />\n <TableCell colSpan={5}>\n <div className=\"space-y-2 rounded bg-surface-2 p-3 text-xs\">\n {g.body && (\n <div>\n <div className=\"text-text-dim\">{t('goals.body')}</div>\n <pre className=\"mt-1 whitespace-pre-wrap break-words\">{g.body}</pre>\n </div>\n )}\n {g.progressLog.length > 0 && (\n <div>\n <div className=\"text-text-dim\">\n {t('goals.recentProgress', { count: g.progressLog.length })}\n </div>\n <ul className=\"mt-1 space-y-1\">\n {g.progressLog.slice().reverse().map((n, i) => (\n <li key={i} className=\"font-mono text-[11px]\">\n <span className=\"text-text-dim\">{n.ts.slice(0, 19)} ({n.by})</span> {n.text}\n </li>\n ))}\n </ul>\n </div>\n )}\n <div className=\"text-[11px] text-text-dim\">\n {t('goals.created', { at: g.createdAt })}\n {g.closedAt ? ` · ${t('goals.closed', { at: g.closedAt })}` : ''}\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n )\n })}\n </TableBody>\n </Table>\n </section>\n )}\n </div>\n )\n}\n\nfunction EmptySection(): JSX.Element {\n const { t } = useTranslation('tasks')\n return (\n <section className=\"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim\">\n {t('goals.empty')}\n <div className=\"mt-2\">\n <CircleDashed className=\"mx-auto h-8 w-8 opacity-30\" />\n </div>\n </section>\n )\n}\n"],"names":["CircleDashed","createLucideIcon","CirclePause","Target","TasksGoalsRoute","t","useTranslation","listQuery","useGoalsList","updateStatus","useGoalUpdateStatus","expandedId","setExpandedId","useState","onChangeStatus","g","status","toast","err","rows","jsxs","jsx","Badge","Button","Loader2","RefreshCcw","EmptySection","Table","TableHeader","TableRow","TableHead","TableBody","isExpanded","Fragment","TableCell","PauseCircle","CheckCircle2","XCircle","n","i"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as p,e as f,j as e,B as g,c as y}from"./index-
|
|
2
|
-
//# sourceMappingURL=health-
|
|
1
|
+
import{u as p,e as f,j as e,B as g,c as y}from"./index-DEWFfW_Z.js";import{r as N}from"./react-DlP5eolq.js";import{E as v}from"./empty-state-D9Hi0Atm.js";import{T as w,a as C,b as h,c as i,d as M,e as o}from"./table-BbAOSyc8.js";import{u as L}from"./use-observability-Coj02yDo.js";import{L as T}from"./loader-circle-Bbw4pEyE.js";import{R as k}from"./refresh-ccw-uNKeBeRl.js";import{A as D}from"./activity-B7T7YFlD.js";import"./useQuery-CY2iazjN.js";function P(){const{t:s}=p(["observability","common"]),[l]=f(),n=Math.max(1,Number(l.get("days"))||7),{data:c,isLoading:u,isFetching:m,refetch:j}=L(n),a=c?.totals,d=c?.byDay??[],b=N.useMemo(()=>d.reduce((t,x)=>x.calls>t?x.calls:t,0),[d]);return e.jsxs("div",{className:"mx-auto flex max-w-7xl 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("health.title")}),e.jsxs(g,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>j(),disabled:m,"aria-label":s("actions.refresh",{ns:"common"}),children:[m?e.jsx(T,{className:"h-4 w-4 animate-spin"}):e.jsx(k,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("actions.refresh",{ns:"common"})})]})]}),c&&e.jsxs("p",{className:"text-xs text-text-dim tabular-nums",children:[c.since," → ",c.until]})]}),u?e.jsx("div",{className:"h-48 w-full rounded-md bg-surface-2 animate-pulse"}):!a||a.calls===0&&d.length===0?e.jsx(v,{icon:e.jsx(D,{}),title:s("health.empty.title"),description:s("health.empty.description")}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-6",children:[e.jsx(r,{label:s("health.kpi.calls"),value:String(a.calls),tone:"info"}),e.jsx(r,{label:s("health.kpi.cost"),value:`$${a.cost.toFixed(4)}`,tone:"info"}),e.jsx(r,{label:s("health.kpi.errors"),value:String(a.errors),tone:a.errors>0?"danger":"success"}),e.jsx(r,{label:s("health.kpi.errorRate"),value:`${(a.errorRate*100).toFixed(1)}%`,tone:a.errorRate>.05?"warning":"success"}),e.jsx(r,{label:s("health.kpi.avgLatencyMs"),value:`${Math.round(a.avgLatencyMs)}ms`,tone:"info"}),e.jsx(r,{label:s("health.kpi.p95LatencyMs"),value:`${Math.round(a.p95LatencyMs)}ms`,tone:"info"})]}),e.jsxs("div",{children:[e.jsx("h2",{className:"mb-2 text-sm font-medium uppercase tracking-wide text-text-dim",children:s("health.byDay")}),e.jsxs(w,{children:[e.jsx(C,{children:e.jsxs(h,{children:[e.jsx(i,{className:"w-28",children:s("health.byDayCol.date")}),e.jsx(i,{children:s("health.byDayCol.calls")}),e.jsx(i,{className:"w-24",children:s("health.byDayCol.cost")}),e.jsx(i,{className:"w-24",children:s("health.byDayCol.errors")}),e.jsx(i,{className:"w-32",children:s("health.byDayCol.avgLatencyMs")})]})}),e.jsx(M,{children:d.map(t=>e.jsxs(h,{children:[e.jsx(o,{className:"font-mono text-xs",children:t.date}),e.jsx(o,{children:e.jsx(S,{value:t.calls,max:b})}),e.jsxs(o,{className:"tabular-nums",children:["$",t.cost.toFixed(4)]}),e.jsx(o,{className:"tabular-nums",children:e.jsx("span",{className:t.errors>0?"text-danger":"text-text-dim",children:t.errors})}),e.jsxs(o,{className:"tabular-nums",children:[Math.round(t.avgLatencyMs),"ms"]})]},t.date))})]})]})]})]})}const R={info:"border-info/30 text-info",success:"border-success/30 text-success",warning:"border-warning/30 text-warning",danger:"border-danger/30 text-danger"};function r({label:s,value:l,tone:n}){return e.jsxs("div",{className:y("rounded-md border bg-surface px-3 py-2",R[n]),children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-text-dim",children:s}),e.jsx("div",{className:"text-xl font-semibold tabular-nums",children:l})]})}function S({value:s,max:l}){const n=l>0?s/l*100:0;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"relative h-3 w-full max-w-xs overflow-hidden rounded bg-surface-2",children:e.jsx("div",{className:"absolute inset-y-0 left-0 bg-accent/60",style:{width:`${n}%`}})}),e.jsx("span",{className:"tabular-nums text-sm text-text-dim",children:s})]})}export{P as default};
|
|
2
|
+
//# sourceMappingURL=health-Ba_mY0Ts.js.map
|