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 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.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const a=e("RefreshCcw",[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]]);export{a as R};
|
|
7
|
-
//# sourceMappingURL=refresh-ccw-
|
|
7
|
+
//# sourceMappingURL=refresh-ccw-uNKeBeRl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-ccw-
|
|
1
|
+
{"version":3,"file":"refresh-ccw-uNKeBeRl.js","sources":["../../node_modules/lucide-react/dist/esm/icons/refresh-ccw.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 RefreshCcw = createLucideIcon(\"RefreshCcw\", [\n [\"path\", { d: \"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"14sxne\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\", key: \"1hlbsb\" }],\n [\"path\", { d: \"M16 16h5v5\", key: \"ccwih5\" }]\n]);\n\nexport { RefreshCcw as default };\n//# sourceMappingURL=refresh-ccw.js.map\n"],"names":["RefreshCcw","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAaC,EAAiB,aAAc,CAChD,CAAC,OAAQ,CAAE,EAAG,qDAAsD,IAAK,QAAQ,CAAE,EACnF,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,sDAAuD,IAAK,QAAQ,CAAE,EACpF,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{n as B,a as w,b as v,d as y,u as D,e as K,j as e,k as M,B as d,T as E,S as L,f as q,g as A,h as F,i as V,l as h,m as b}from"./index-
|
|
1
|
+
import{n as B,a as w,b as v,d as y,u as D,e as K,j as e,k as M,B as d,T as E,S as L,f as q,g as A,h as F,i as V,l as h,m as b}from"./index-DEWFfW_Z.js";import{r as x}from"./react-DlP5eolq.js";import{D as _}from"./data-table-DswkWUfG.js";import{E as Q}from"./empty-state-D9Hi0Atm.js";import{S as $}from"./status-badge-Ryzf96Pl.js";import{C as H}from"./confirm-dialog-DlUsSur3.js";import{D as U,a as Z,b as G,c as J,d as W,e as X}from"./dialog-Ceo4YuXy.js";import{u as Y}from"./useQuery-CY2iazjN.js";import{C as ee}from"./clock-CG5dlBGB.js";import{L as se}from"./loader-circle-Bbw4pEyE.js";import{R as te}from"./refresh-ccw-uNKeBeRl.js";import{B as ae}from"./bell-CV88-ul6.js";import"./table-BbAOSyc8.js";import"./arrow-up-BOADc9ce.js";import"./arrow-down-SLWKqtDc.js";import"./x-D1iSuoqg.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 ne=B("BellOff",[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742",key:"178tsu"}],["path",{d:"m2 2 20 20",key:"1ooewy"}],["path",{d:"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05",key:"1hqiys"}]]),C={all:["reminders"],list:s=>["reminders","list",s]};function ie(s){return Y({queryKey:C.list(s),queryFn:()=>y.listReminders(s),refetchInterval:5e3,refetchIntervalInBackground:!1})}function re(){const s=w();return v({mutationFn:a=>y.cancelReminder(a),onSuccess:()=>s.invalidateQueries({queryKey:C.all})})}function le(){const s=w();return v({mutationFn:({id:a,body:i})=>y.snoozeReminder(a,i),onSuccess:()=>s.invalidateQueries({queryKey:C.all})})}const oe=["pending","firing","fired","cancelled","failed"],ce=[{duration:"5m",i18nKey:"snooze.preset5m"},{duration:"30m",i18nKey:"snooze.preset30m"},{duration:"1h",i18nKey:"snooze.preset1h"},{duration:"1d",i18nKey:"snooze.preset1d"}];function Te(){const{t:s}=D(["reminders","common"]),[a,i]=K(),r=a.get("status")??"pending",l=x.useMemo(()=>({status:r,limit:200}),[r]),{data:o,isLoading:z,isFetching:N,refetch:T}=ie(l),P=o?.reminders??[],m=re(),c=le(),[f,S]=x.useState(null),[p,g]=x.useState(null);function k(t){const n=new URLSearchParams(a);for(const[u,j]of Object.entries(t))j==null||j===""?n.delete(u):n.set(u,j);i(n,{replace:!0})}async function R(){if(f!=null)try{await m.mutateAsync(f),h.success(s("toast.cancelled"))}catch(t){const{message:n}=b(t,s);throw h.error(n),t}}async function O(t){if(p!=null)try{await c.mutateAsync({id:p,body:{duration:t}}),h.success(s("snooze.toastOk",{duration:t})),g(null)}catch(n){const{message:u}=b(n,s);h.error(u)}}const I=x.useMemo(()=>[{id:"id",header:s("col.id"),cell:t=>e.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",t.id]}),headClassName:"w-16"},{id:"fireAt",header:s("col.fireAt"),cell:t=>e.jsx("span",{className:"font-medium tabular-nums",children:me(t.fire_at)}),headClassName:"w-40"},{id:"text",header:s("col.text"),cell:t=>e.jsx("span",{className:"line-clamp-2 text-text-dim",children:t.text}),asCardTitle:!0},{id:"status",header:s("col.status"),cell:t=>e.jsx($,{status:t.status,children:s(`status.${t.status}`,{defaultValue:t.status})}),headClassName:"w-28"},{id:"platform",header:s("col.platform"),cell:t=>e.jsx("span",{className:"text-text-dim",children:t.platform}),headClassName:"w-24",hideOnMobile:!0},{id:"recurrence",header:s("col.recurrence"),cell:t=>t.recurrence_label?e.jsx(M,{variant:"info",children:t.recurrence_label}):e.jsx("span",{className:"text-text-muted",children:"—"}),headClassName:"w-36",hideOnMobile:!0},{id:"source",header:s("col.source"),cell:t=>e.jsx("span",{className:"text-text-dim",children:s(`source.${t.source}`,{defaultValue:t.source})}),headClassName:"w-24",hideOnMobile:!0},{id:"actions",header:"",cell:t=>t.status==="pending"?e.jsxs("div",{className:"flex justify-end gap-1",children:[e.jsxs(d,{variant:"ghost",size:"sm",onClick:n=>{n.stopPropagation(),g(t.id)},disabled:c.isPending||m.isPending,children:[e.jsx(ee,{className:"h-3 w-3"}),s("action.snooze")]}),e.jsxs(d,{variant:"outline",size:"sm",onClick:n=>{n.stopPropagation(),S(t.id)},disabled:m.isPending||c.isPending,children:[e.jsx(ne,{className:"h-3 w-3"}),s("action.cancel")]})]}):null,headClassName:"w-48"}],[s,m.isPending,c.isPending]);return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(E,{}),e.jsxs("main",{className:"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe",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("pageTitle")}),e.jsxs(d,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>T(),disabled:N,"aria-label":s("actions.refresh",{ns:"common"}),children:[N?e.jsx(se,{className:"h-4 w-4 animate-spin"}):e.jsx(te,{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-center gap-2",children:[e.jsx("label",{className:"text-sm text-text-dim",htmlFor:"status-filter",children:s("filter.status")}),e.jsxs(L,{value:r,onValueChange:t=>k({status:t}),children:[e.jsx(q,{id:"status-filter",className:"w-[160px]",children:e.jsx(A,{})}),e.jsx(F,{children:oe.map(t=>e.jsx(V,{value:t,children:s(`status.${t}`,{defaultValue:t})},t))})]})]}),e.jsx(_,{columns:I,rows:P,getRowId:t=>String(t.id),loading:z,emptyState:e.jsx(Q,{icon:e.jsx(ae,{}),title:s("empty.title"),description:s("empty.description")})}),e.jsx(H,{open:f!=null,onOpenChange:t=>{t||S(null)},title:s("action.confirmCancel"),description:s("action.confirmCancelDesc"),intent:"danger",confirmLabel:s("action.cancel"),onConfirm:R}),e.jsx(de,{open:p!=null,busy:c.isPending,onOpenChange:t=>{t||g(null)},onPick:O})]})]})}function de({open:s,busy:a,onOpenChange:i,onPick:r}){const{t:l}=D(["reminders","common"]);return e.jsx(U,{open:s,onOpenChange:a?()=>{}:i,children:e.jsxs(Z,{children:[e.jsxs(G,{children:[e.jsx(J,{children:l("snooze.title")}),e.jsx(W,{children:l("snooze.description")})]}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:ce.map(o=>e.jsx(d,{type:"button",variant:"outline",disabled:a,onClick:()=>void r(o.duration),children:l(o.i18nKey)},o.duration))}),e.jsx(X,{children:e.jsx(d,{type:"button",variant:"secondary",disabled:a,onClick:()=>i(!1),children:l("actions.cancel",{ns:"common"})})})]})})}function me(s){try{const a=new Date(s);if(Number.isNaN(a.getTime()))return s;const i=new Date;return a.toDateString()===i.toDateString()?a.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"}):a.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return s}}export{Te as default};
|
|
7
|
-
//# sourceMappingURL=reminders-
|
|
7
|
+
//# sourceMappingURL=reminders-DHM8K0_O.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reminders-Cb6Izedg.js","sources":["../../node_modules/lucide-react/dist/esm/icons/bell-off.js","../../src/hooks/use-reminders.ts","../../src/routes/reminders.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 BellOff = createLucideIcon(\"BellOff\", [\n [\"path\", { d: \"M10.268 21a2 2 0 0 0 3.464 0\", key: \"vwvbt9\" }],\n [\n \"path\",\n {\n d: \"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742\",\n key: \"178tsu\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }],\n [\"path\", { d: \"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\", key: \"1hqiys\" }]\n]);\n\nexport { BellOff as default };\n//# sourceMappingURL=bell-off.js.map\n","/**\n * useReminders — react-query wrappers for the reminders domain.\n *\n * useReminders(query) — list pending (default) or by status\n * useCancelReminder() — POST /api/reminders/:id/cancel\n * useSnoozeReminder() — POST /api/reminders/:id/snooze\n *\n * Reminders aren't on the SSE event-bus today; the page combines a\n * 5s react-query poll with a manual Refresh button. When a snooze\n * mutation lands, both the original AND the new reminder change\n * (one cancelled, one pending) — invalidating the full 'reminders'\n * key catches both.\n */\n\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type {\n CancelReminderResponse,\n ListRemindersQuery,\n ListRemindersResponse,\n SnoozeReminderBody,\n SnoozeReminderResponse,\n} from '@/types/api'\n\nexport const remindersKeys = {\n all: ['reminders'] as const,\n list: (q: ListRemindersQuery) => ['reminders', 'list', q] as const,\n}\n\nexport function useReminders(query: ListRemindersQuery) {\n return useQuery<ListRemindersResponse>({\n queryKey: remindersKeys.list(query),\n queryFn: () => api.listReminders(query),\n refetchInterval: 5000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useInvalidateReminders() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: remindersKeys.all })\n}\n\nexport function useCancelReminder() {\n const qc = useQueryClient()\n return useMutation<CancelReminderResponse, Error, number>({\n mutationFn: (id) => api.cancelReminder(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n\nexport function useSnoozeReminder() {\n const qc = useQueryClient()\n return useMutation<\n SnoozeReminderResponse,\n Error,\n { id: number; body: SnoozeReminderBody }\n >({\n mutationFn: ({ id, body }) => api.snoozeReminder(id, body),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n","/**\n * /reminders — queued-reminder list with cancel + snooze.\n *\n * Composition: Topbar + filter row + DataTable + ConfirmDialog\n * (cancel) + a custom <SnoozeDialog> with duration presets that\n * map to the backend's parseDuration vocabulary.\n *\n * Mutations only enabled on `pending` rows; firing/fired/cancelled/\n * failed stay read-only. The DataTable's last column is per-row\n * action buttons.\n *\n * No SSE channel for reminders — 5s react-query poll covers the\n * common case (reminders fire on minute boundaries; latency to\n * surface a firing transition is rarely UX-critical).\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Bell, BellOff, Clock, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { Topbar } from '@/components/shell/topbar'\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useReminders,\n useCancelReminder,\n useSnoozeReminder,\n} from '@/hooks/use-reminders'\nimport { describeError } from '@/lib/api/errors'\nimport type { Reminder, ReminderStatus } from '@/types/api'\n\nconst STATUS_OPTIONS: ReminderStatus[] = ['pending', 'firing', 'fired', 'cancelled', 'failed']\n\ninterface SnoozePreset {\n /** Backend parseDuration string. */\n duration: string\n /** i18n key (inside the `snooze` section). */\n i18nKey: string\n}\n\nconst SNOOZE_PRESETS: SnoozePreset[] = [\n { duration: '5m', i18nKey: 'snooze.preset5m' },\n { duration: '30m', i18nKey: 'snooze.preset30m' },\n { duration: '1h', i18nKey: 'snooze.preset1h' },\n { duration: '1d', i18nKey: 'snooze.preset1d' },\n]\n\nexport default function RemindersRoute(): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n const [params, setParams] = useSearchParams()\n const status = (params.get('status') as ReminderStatus | null) ?? 'pending'\n\n const query = useMemo(\n () => ({ status, limit: 200 }),\n [status],\n )\n const { data, isLoading, isFetching, refetch } = useReminders(query)\n const reminders = data?.reminders ?? []\n\n const cancel = useCancelReminder()\n const snooze = useSnoozeReminder()\n\n const [confirmCancelId, setConfirmCancelId] = useState<number | null>(null)\n const [snoozeTargetId, setSnoozeTargetId] = useState<number | null>(null)\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 setParams(next, { replace: true })\n }\n\n async function onConfirmCancel(): Promise<void> {\n if (confirmCancelId == null) return\n try {\n await cancel.mutateAsync(confirmCancelId)\n toast.success(t('toast.cancelled'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onConfirmSnooze(duration: string): Promise<void> {\n if (snoozeTargetId == null) return\n try {\n await snooze.mutateAsync({ id: snoozeTargetId, body: { duration } })\n toast.success(t('snooze.toastOk', { duration }))\n setSnoozeTargetId(null)\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n const columns: DataTableColumn<Reminder>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'fireAt',\n header: t('col.fireAt'),\n cell: (r) => <span className=\"font-medium tabular-nums\">{formatTime(r.fire_at)}</span>,\n headClassName: 'w-40',\n },\n {\n id: 'text',\n header: t('col.text'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.text}</span>,\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'platform',\n header: t('col.platform'),\n cell: (r) => <span className=\"text-text-dim\">{r.platform}</span>,\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'recurrence',\n header: t('col.recurrence'),\n cell: (r) =>\n r.recurrence_label ? (\n <Badge variant=\"info\">{r.recurrence_label}</Badge>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n headClassName: 'w-36',\n hideOnMobile: true,\n },\n {\n id: 'source',\n header: t('col.source'),\n cell: (r) => (\n <span className=\"text-text-dim\">{t(`source.${r.source}`, { defaultValue: r.source })}</span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) =>\n r.status === 'pending' ? (\n <div className=\"flex justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setSnoozeTargetId(r.id)\n }}\n disabled={snooze.isPending || cancel.isPending}\n >\n <Clock className=\"h-3 w-3\" />\n {t('action.snooze')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmCancelId(r.id)\n }}\n disabled={cancel.isPending || snooze.isPending}\n >\n <BellOff className=\"h-3 w-3\" />\n {t('action.cancel')}\n </Button>\n </div>\n ) : null,\n headClassName: 'w-48',\n },\n ],\n [t, cancel.isPending, snooze.isPending],\n )\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <main className=\"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe\">\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('pageTitle')}</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-center gap-2\">\n <label className=\"text-sm text-text-dim\" htmlFor=\"status-filter\">\n {t('filter.status')}\n </label>\n <Select\n value={status}\n onValueChange={(v) => patchParams({ status: v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <DataTable\n columns={columns}\n rows={reminders}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<Bell />}\n title={t('empty.title')}\n description={t('empty.description')}\n />\n }\n />\n\n <ConfirmDialog\n open={confirmCancelId != null}\n onOpenChange={(open) => {\n if (!open) setConfirmCancelId(null)\n }}\n title={t('action.confirmCancel')}\n description={t('action.confirmCancelDesc')}\n intent=\"danger\"\n confirmLabel={t('action.cancel')}\n onConfirm={onConfirmCancel}\n />\n\n <SnoozeDialog\n open={snoozeTargetId != null}\n busy={snooze.isPending}\n onOpenChange={(open) => {\n if (!open) setSnoozeTargetId(null)\n }}\n onPick={onConfirmSnooze}\n />\n </main>\n </div>\n )\n}\n\ninterface SnoozeDialogProps {\n open: boolean\n busy: boolean\n onOpenChange: (open: boolean) => void\n onPick: (duration: string) => void | Promise<void>\n}\n\nfunction SnoozeDialog({ open, busy, onOpenChange, onPick }: SnoozeDialogProps): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n return (\n <Dialog open={open} onOpenChange={busy ? () => {} : onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{t('snooze.title')}</DialogTitle>\n <DialogDescription>{t('snooze.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"grid grid-cols-2 gap-2\">\n {SNOOZE_PRESETS.map((p) => (\n <Button\n key={p.duration}\n type=\"button\"\n variant=\"outline\"\n disabled={busy}\n onClick={() => void onPick(p.duration)}\n >\n {t(p.i18nKey)}\n </Button>\n ))}\n </div>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onOpenChange(false)}\n >\n {t('actions.cancel', { ns: 'common' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const now = new Date()\n const sameDay = d.toDateString() === now.toDateString()\n if (sameDay) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })\n }\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["BellOff","createLucideIcon","remindersKeys","q","useReminders","query","useQuery","api","useCancelReminder","qc","useQueryClient","useMutation","id","useSnoozeReminder","body","STATUS_OPTIONS","SNOOZE_PRESETS","RemindersRoute","t","useTranslation","params","setParams","useSearchParams","status","useMemo","data","isLoading","isFetching","refetch","reminders","cancel","snooze","confirmCancelId","setConfirmCancelId","useState","snoozeTargetId","setSnoozeTargetId","patchParams","patch","next","k","v","onConfirmCancel","toast","err","message","describeError","onConfirmSnooze","duration","columns","r","jsxs","jsx","formatTime","StatusBadge","Badge","Button","e","Clock","Topbar","Loader2","RefreshCcw","Select","SelectTrigger","SelectValue","SelectContent","s","SelectItem","DataTable","EmptyState","Bell","ConfirmDialog","open","SnoozeDialog","busy","onOpenChange","onPick","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","p","DialogFooter","iso","d","now"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"reminders-DHM8K0_O.js","sources":["../../node_modules/lucide-react/dist/esm/icons/bell-off.js","../../src/hooks/use-reminders.ts","../../src/routes/reminders.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 BellOff = createLucideIcon(\"BellOff\", [\n [\"path\", { d: \"M10.268 21a2 2 0 0 0 3.464 0\", key: \"vwvbt9\" }],\n [\n \"path\",\n {\n d: \"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742\",\n key: \"178tsu\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }],\n [\"path\", { d: \"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\", key: \"1hqiys\" }]\n]);\n\nexport { BellOff as default };\n//# sourceMappingURL=bell-off.js.map\n","/**\n * useReminders — react-query wrappers for the reminders domain.\n *\n * useReminders(query) — list pending (default) or by status\n * useCancelReminder() — POST /api/reminders/:id/cancel\n * useSnoozeReminder() — POST /api/reminders/:id/snooze\n *\n * Reminders aren't on the SSE event-bus today; the page combines a\n * 5s react-query poll with a manual Refresh button. When a snooze\n * mutation lands, both the original AND the new reminder change\n * (one cancelled, one pending) — invalidating the full 'reminders'\n * key catches both.\n */\n\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type {\n CancelReminderResponse,\n ListRemindersQuery,\n ListRemindersResponse,\n SnoozeReminderBody,\n SnoozeReminderResponse,\n} from '@/types/api'\n\nexport const remindersKeys = {\n all: ['reminders'] as const,\n list: (q: ListRemindersQuery) => ['reminders', 'list', q] as const,\n}\n\nexport function useReminders(query: ListRemindersQuery) {\n return useQuery<ListRemindersResponse>({\n queryKey: remindersKeys.list(query),\n queryFn: () => api.listReminders(query),\n refetchInterval: 5000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useInvalidateReminders() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: remindersKeys.all })\n}\n\nexport function useCancelReminder() {\n const qc = useQueryClient()\n return useMutation<CancelReminderResponse, Error, number>({\n mutationFn: (id) => api.cancelReminder(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n\nexport function useSnoozeReminder() {\n const qc = useQueryClient()\n return useMutation<\n SnoozeReminderResponse,\n Error,\n { id: number; body: SnoozeReminderBody }\n >({\n mutationFn: ({ id, body }) => api.snoozeReminder(id, body),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n","/**\n * /reminders — queued-reminder list with cancel + snooze.\n *\n * Composition: Topbar + filter row + DataTable + ConfirmDialog\n * (cancel) + a custom <SnoozeDialog> with duration presets that\n * map to the backend's parseDuration vocabulary.\n *\n * Mutations only enabled on `pending` rows; firing/fired/cancelled/\n * failed stay read-only. The DataTable's last column is per-row\n * action buttons.\n *\n * No SSE channel for reminders — 5s react-query poll covers the\n * common case (reminders fire on minute boundaries; latency to\n * surface a firing transition is rarely UX-critical).\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Bell, BellOff, Clock, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { Topbar } from '@/components/shell/topbar'\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useReminders,\n useCancelReminder,\n useSnoozeReminder,\n} from '@/hooks/use-reminders'\nimport { describeError } from '@/lib/api/errors'\nimport type { Reminder, ReminderStatus } from '@/types/api'\n\nconst STATUS_OPTIONS: ReminderStatus[] = ['pending', 'firing', 'fired', 'cancelled', 'failed']\n\ninterface SnoozePreset {\n /** Backend parseDuration string. */\n duration: string\n /** i18n key (inside the `snooze` section). */\n i18nKey: string\n}\n\nconst SNOOZE_PRESETS: SnoozePreset[] = [\n { duration: '5m', i18nKey: 'snooze.preset5m' },\n { duration: '30m', i18nKey: 'snooze.preset30m' },\n { duration: '1h', i18nKey: 'snooze.preset1h' },\n { duration: '1d', i18nKey: 'snooze.preset1d' },\n]\n\nexport default function RemindersRoute(): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n const [params, setParams] = useSearchParams()\n const status = (params.get('status') as ReminderStatus | null) ?? 'pending'\n\n const query = useMemo(\n () => ({ status, limit: 200 }),\n [status],\n )\n const { data, isLoading, isFetching, refetch } = useReminders(query)\n const reminders = data?.reminders ?? []\n\n const cancel = useCancelReminder()\n const snooze = useSnoozeReminder()\n\n const [confirmCancelId, setConfirmCancelId] = useState<number | null>(null)\n const [snoozeTargetId, setSnoozeTargetId] = useState<number | null>(null)\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 setParams(next, { replace: true })\n }\n\n async function onConfirmCancel(): Promise<void> {\n if (confirmCancelId == null) return\n try {\n await cancel.mutateAsync(confirmCancelId)\n toast.success(t('toast.cancelled'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onConfirmSnooze(duration: string): Promise<void> {\n if (snoozeTargetId == null) return\n try {\n await snooze.mutateAsync({ id: snoozeTargetId, body: { duration } })\n toast.success(t('snooze.toastOk', { duration }))\n setSnoozeTargetId(null)\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n const columns: DataTableColumn<Reminder>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'fireAt',\n header: t('col.fireAt'),\n cell: (r) => <span className=\"font-medium tabular-nums\">{formatTime(r.fire_at)}</span>,\n headClassName: 'w-40',\n },\n {\n id: 'text',\n header: t('col.text'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.text}</span>,\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'platform',\n header: t('col.platform'),\n cell: (r) => <span className=\"text-text-dim\">{r.platform}</span>,\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'recurrence',\n header: t('col.recurrence'),\n cell: (r) =>\n r.recurrence_label ? (\n <Badge variant=\"info\">{r.recurrence_label}</Badge>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n headClassName: 'w-36',\n hideOnMobile: true,\n },\n {\n id: 'source',\n header: t('col.source'),\n cell: (r) => (\n <span className=\"text-text-dim\">{t(`source.${r.source}`, { defaultValue: r.source })}</span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) =>\n r.status === 'pending' ? (\n <div className=\"flex justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setSnoozeTargetId(r.id)\n }}\n disabled={snooze.isPending || cancel.isPending}\n >\n <Clock className=\"h-3 w-3\" />\n {t('action.snooze')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmCancelId(r.id)\n }}\n disabled={cancel.isPending || snooze.isPending}\n >\n <BellOff className=\"h-3 w-3\" />\n {t('action.cancel')}\n </Button>\n </div>\n ) : null,\n headClassName: 'w-48',\n },\n ],\n [t, cancel.isPending, snooze.isPending],\n )\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <main className=\"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe\">\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('pageTitle')}</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-center gap-2\">\n <label className=\"text-sm text-text-dim\" htmlFor=\"status-filter\">\n {t('filter.status')}\n </label>\n <Select\n value={status}\n onValueChange={(v) => patchParams({ status: v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <DataTable\n columns={columns}\n rows={reminders}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<Bell />}\n title={t('empty.title')}\n description={t('empty.description')}\n />\n }\n />\n\n <ConfirmDialog\n open={confirmCancelId != null}\n onOpenChange={(open) => {\n if (!open) setConfirmCancelId(null)\n }}\n title={t('action.confirmCancel')}\n description={t('action.confirmCancelDesc')}\n intent=\"danger\"\n confirmLabel={t('action.cancel')}\n onConfirm={onConfirmCancel}\n />\n\n <SnoozeDialog\n open={snoozeTargetId != null}\n busy={snooze.isPending}\n onOpenChange={(open) => {\n if (!open) setSnoozeTargetId(null)\n }}\n onPick={onConfirmSnooze}\n />\n </main>\n </div>\n )\n}\n\ninterface SnoozeDialogProps {\n open: boolean\n busy: boolean\n onOpenChange: (open: boolean) => void\n onPick: (duration: string) => void | Promise<void>\n}\n\nfunction SnoozeDialog({ open, busy, onOpenChange, onPick }: SnoozeDialogProps): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n return (\n <Dialog open={open} onOpenChange={busy ? () => {} : onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{t('snooze.title')}</DialogTitle>\n <DialogDescription>{t('snooze.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"grid grid-cols-2 gap-2\">\n {SNOOZE_PRESETS.map((p) => (\n <Button\n key={p.duration}\n type=\"button\"\n variant=\"outline\"\n disabled={busy}\n onClick={() => void onPick(p.duration)}\n >\n {t(p.i18nKey)}\n </Button>\n ))}\n </div>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onOpenChange(false)}\n >\n {t('actions.cancel', { ns: 'common' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const now = new Date()\n const sameDay = d.toDateString() === now.toDateString()\n if (sameDay) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })\n }\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["BellOff","createLucideIcon","remindersKeys","q","useReminders","query","useQuery","api","useCancelReminder","qc","useQueryClient","useMutation","id","useSnoozeReminder","body","STATUS_OPTIONS","SNOOZE_PRESETS","RemindersRoute","t","useTranslation","params","setParams","useSearchParams","status","useMemo","data","isLoading","isFetching","refetch","reminders","cancel","snooze","confirmCancelId","setConfirmCancelId","useState","snoozeTargetId","setSnoozeTargetId","patchParams","patch","next","k","v","onConfirmCancel","toast","err","message","describeError","onConfirmSnooze","duration","columns","r","jsxs","jsx","formatTime","StatusBadge","Badge","Button","e","Clock","Topbar","Loader2","RefreshCcw","Select","SelectTrigger","SelectValue","SelectContent","s","SelectItem","DataTable","EmptyState","Bell","ConfirmDialog","open","SnoozeDialog","busy","onOpenChange","onPick","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","p","DialogFooter","iso","d","now"],"mappings":"uxBAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,GAAUC,EAAiB,UAAW,CAC1C,CAAC,OAAQ,CAAE,EAAG,+BAAgC,IAAK,QAAQ,CAAE,EAC7D,CACE,OACA,CACE,EAAG,6EACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,yDAA0D,IAAK,QAAQ,CAAE,CACzF,CAAC,ECIYC,EAAgB,CAC3B,IAAM,CAAC,WAAW,EAClB,KAAOC,GAA0B,CAAC,YAAa,OAAQA,CAAC,CAC1D,EAEO,SAASC,GAAaC,EAA2B,CACtD,OAAOC,EAAgC,CACrC,SAAUJ,EAAc,KAAKG,CAAK,EAClC,QAAS,IAAME,EAAI,cAAcF,CAAK,EACtC,gBAAiB,IACjB,4BAA6B,EAAA,CAC9B,CACH,CAOO,SAASG,IAAoB,CAClC,MAAMC,EAAKC,EAAA,EACX,OAAOC,EAAmD,CACxD,WAAaC,GAAOL,EAAI,eAAeK,CAAE,EACzC,UAAW,IAAMH,EAAG,kBAAkB,CAAE,SAAUP,EAAc,IAAK,CAAA,CACtE,CACH,CAEO,SAASW,IAAoB,CAClC,MAAMJ,EAAKC,EAAA,EACX,OAAOC,EAIL,CACA,WAAY,CAAC,CAAE,GAAAC,EAAI,KAAAE,KAAWP,EAAI,eAAeK,EAAIE,CAAI,EACzD,UAAW,IAAML,EAAG,kBAAkB,CAAE,SAAUP,EAAc,IAAK,CAAA,CACtE,CACH,CCTA,MAAMa,GAAmC,CAAC,UAAW,SAAU,QAAS,YAAa,QAAQ,EASvFC,GAAiC,CACrC,CAAE,SAAU,KAAM,QAAS,iBAAA,EAC3B,CAAE,SAAU,MAAO,QAAS,kBAAA,EAC5B,CAAE,SAAU,KAAM,QAAS,iBAAA,EAC3B,CAAE,SAAU,KAAM,QAAS,iBAAA,CAC7B,EAEA,SAAwBC,IAA8B,CACpD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,YAAa,QAAQ,CAAC,EAC9C,CAACC,EAAQC,CAAS,EAAIC,EAAA,EACtBC,EAAUH,EAAO,IAAI,QAAQ,GAA+B,UAE5Df,EAAQmB,EAAAA,QACZ,KAAO,CAAE,OAAAD,EAAQ,MAAO,MACxB,CAACA,CAAM,CAAA,EAEH,CAAE,KAAAE,EAAM,UAAAC,EAAW,WAAAC,EAAY,QAAAC,CAAA,EAAYxB,GAAaC,CAAK,EAC7DwB,EAAYJ,GAAM,WAAa,CAAA,EAE/BK,EAAStB,GAAA,EACTuB,EAASlB,GAAA,EAET,CAACmB,EAAiBC,CAAkB,EAAIC,EAAAA,SAAwB,IAAI,EACpE,CAACC,EAAgBC,CAAiB,EAAIF,EAAAA,SAAwB,IAAI,EAExE,SAASG,EAAYC,EAA4C,CAC/D,MAAMC,EAAO,IAAI,gBAAgBnB,CAAM,EACvC,SAAW,CAACoB,EAAGC,CAAC,IAAK,OAAO,QAAQH,CAAK,EACnCG,GAAK,MAAQA,IAAM,GAAIF,EAAK,OAAOC,CAAC,EACnCD,EAAK,IAAIC,EAAGC,CAAC,EAEpBpB,EAAUkB,EAAM,CAAE,QAAS,EAAA,CAAM,CACnC,CAEA,eAAeG,GAAiC,CAC9C,GAAIV,GAAmB,KACvB,GAAI,CACF,MAAMF,EAAO,YAAYE,CAAe,EACxCW,EAAM,QAAQzB,EAAE,iBAAiB,CAAC,CACpC,OAAS0B,EAAK,CACZ,KAAM,CAAE,QAAAC,CAAA,EAAYC,EAAcF,EAAK1B,CAAC,EACxCyB,MAAAA,EAAM,MAAME,CAAO,EACbD,CACR,CACF,CAEA,eAAeG,EAAgBC,EAAiC,CAC9D,GAAIb,GAAkB,KACtB,GAAI,CACF,MAAMJ,EAAO,YAAY,CAAE,GAAII,EAAgB,KAAM,CAAE,SAAAa,CAAA,EAAY,EACnEL,EAAM,QAAQzB,EAAE,iBAAkB,CAAE,SAAA8B,CAAA,CAAU,CAAC,EAC/CZ,EAAkB,IAAI,CACxB,OAASQ,EAAK,CACZ,KAAM,CAAE,QAAAC,CAAA,EAAYC,EAAcF,EAAK1B,CAAC,EACxCyB,EAAM,MAAME,CAAO,CACrB,CACF,CAEA,MAAMI,EAAuCzB,EAAAA,QAC3C,IAAM,CACJ,CACE,GAAI,KACJ,OAAQN,EAAE,QAAQ,EAClB,KAAOgC,GAAMC,EAAAA,KAAC,OAAA,CAAK,UAAU,6BAA6B,SAAA,CAAA,IAAED,EAAE,EAAA,EAAG,EACjE,cAAe,MAAA,EAEjB,CACE,GAAI,SACJ,OAAQhC,EAAE,YAAY,EACtB,KAAOgC,GAAME,EAAAA,IAAC,OAAA,CAAK,UAAU,2BAA4B,SAAAC,GAAWH,EAAE,OAAO,CAAA,CAAE,EAC/E,cAAe,MAAA,EAEjB,CACE,GAAI,OACJ,OAAQhC,EAAE,UAAU,EACpB,KAAOgC,GAAME,EAAAA,IAAC,QAAK,UAAU,6BAA8B,WAAE,KAAK,EAClE,YAAa,EAAA,EAEf,CACE,GAAI,SACJ,OAAQlC,EAAE,YAAY,EACtB,KAAOgC,SACJI,EAAA,CAAY,OAAQJ,EAAE,OACpB,SAAAhC,EAAE,UAAUgC,EAAE,MAAM,GAAI,CAAE,aAAcA,EAAE,MAAA,CAAQ,EACrD,EAEF,cAAe,MAAA,EAEjB,CACE,GAAI,WACJ,OAAQhC,EAAE,cAAc,EACxB,KAAOgC,GAAME,EAAAA,IAAC,QAAK,UAAU,gBAAiB,WAAE,SAAS,EACzD,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,aACJ,OAAQlC,EAAE,gBAAgB,EAC1B,KAAOgC,GACLA,EAAE,uBACCK,EAAA,CAAM,QAAQ,OAAQ,SAAAL,EAAE,iBAAiB,EAE1CE,EAAAA,IAAC,OAAA,CAAK,UAAU,kBAAkB,SAAA,IAAC,EAEvC,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,SACJ,OAAQlC,EAAE,YAAY,EACtB,KAAOgC,GACLE,MAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAlC,EAAE,UAAUgC,EAAE,MAAM,GAAI,CAAE,aAAcA,EAAE,MAAA,CAAQ,EAAE,EAEvF,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,UACJ,OAAQ,GACR,KAAOA,GACLA,EAAE,SAAW,UACXC,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAA,EAAAA,KAACK,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAUC,GAAM,CACdA,EAAE,gBAAA,EACFrB,EAAkBc,EAAE,EAAE,CACxB,EACA,SAAUnB,EAAO,WAAaD,EAAO,UAErC,SAAA,CAAAsB,EAAAA,IAACM,GAAA,CAAM,UAAU,SAAA,CAAU,EAC1BxC,EAAE,eAAe,CAAA,CAAA,CAAA,EAEpBiC,EAAAA,KAACK,EAAA,CACC,QAAQ,UACR,KAAK,KACL,QAAUC,GAAM,CACdA,EAAE,gBAAA,EACFxB,EAAmBiB,EAAE,EAAE,CACzB,EACA,SAAUpB,EAAO,WAAaC,EAAO,UAErC,SAAA,CAAAqB,EAAAA,IAACpD,GAAA,CAAQ,UAAU,SAAA,CAAU,EAC5BkB,EAAE,eAAe,CAAA,CAAA,CAAA,CACpB,CAAA,CACF,EACE,KACN,cAAe,MAAA,CACjB,EAEF,CAACA,EAAGY,EAAO,UAAWC,EAAO,SAAS,CAAA,EAGxC,OACEoB,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACO,EAAA,EAAO,EAERR,EAAAA,KAAC,OAAA,CAAK,UAAU,gFACd,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAlC,EAAE,WAAW,EAAE,EACtDiC,EAAAA,KAACK,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAM5B,EAAA,EACf,SAAUD,EACV,aAAYT,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAS,EAAayB,EAAAA,IAACQ,IAAQ,UAAU,sBAAA,CAAuB,EAAKR,EAAAA,IAACS,GAAA,CAAW,UAAU,SAAA,CAAU,EAC7FT,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAlC,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,UAAU,CAAA,CAAE,CAAA,EACtD,EAGAiC,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,EAAAA,IAAC,SAAM,UAAU,wBAAwB,QAAQ,gBAC9C,SAAAlC,EAAE,eAAe,EACpB,EACAiC,EAAAA,KAACW,EAAA,CACC,MAAOvC,EACP,cAAgBkB,GAAMJ,EAAY,CAAE,OAAQI,EAAG,EAE/C,SAAA,CAAAW,EAAAA,IAACW,GAAc,GAAG,gBAAgB,UAAU,YAC1C,SAAAX,EAAAA,IAACY,IAAY,CAAA,CACf,EACAZ,EAAAA,IAACa,GACE,SAAAlD,GAAe,IAAKmD,GACnBd,EAAAA,IAACe,GAAmB,MAAOD,EACxB,WAAE,UAAUA,CAAC,GAAI,CAAE,aAAcA,EAAG,GADtBA,CAEjB,CACD,CAAA,CACH,CAAA,CAAA,CAAA,CACF,EACF,EAEAd,EAAAA,IAACgB,EAAA,CACC,QAAAnB,EACA,KAAMpB,EACN,SAAWqB,GAAM,OAAOA,EAAE,EAAE,EAC5B,QAASxB,EACT,WACE0B,EAAAA,IAACiB,EAAA,CACC,WAAOC,GAAA,EAAK,EACZ,MAAOpD,EAAE,aAAa,EACtB,YAAaA,EAAE,mBAAmB,CAAA,CAAA,CACpC,CAAA,EAIJkC,EAAAA,IAACmB,EAAA,CACC,KAAMvC,GAAmB,KACzB,aAAewC,GAAS,CACjBA,GAAMvC,EAAmB,IAAI,CACpC,EACA,MAAOf,EAAE,sBAAsB,EAC/B,YAAaA,EAAE,0BAA0B,EACzC,OAAO,SACP,aAAcA,EAAE,eAAe,EAC/B,UAAWwB,CAAA,CAAA,EAGbU,EAAAA,IAACqB,GAAA,CACC,KAAMtC,GAAkB,KACxB,KAAMJ,EAAO,UACb,aAAeyC,GAAS,CACjBA,GAAMpC,EAAkB,IAAI,CACnC,EACA,OAAQW,CAAA,CAAA,CACV,CAAA,CACF,CAAA,EACF,CAEJ,CASA,SAAS0B,GAAa,CAAE,KAAAD,EAAM,KAAAE,EAAM,aAAAC,EAAc,OAAAC,GAA0C,CAC1F,KAAM,CAAE,EAAA1D,CAAA,EAAMC,EAAe,CAAC,YAAa,QAAQ,CAAC,EACpD,OACEiC,EAAAA,IAACyB,EAAA,CAAO,KAAAL,EAAY,aAAcE,EAAO,IAAM,CAAC,EAAIC,EAClD,SAAAxB,EAAAA,KAAC2B,EAAA,CACC,SAAA,CAAA3B,OAAC4B,EAAA,CACC,SAAA,CAAA3B,EAAAA,IAAC4B,EAAA,CAAa,SAAA9D,EAAE,cAAc,CAAA,CAAE,EAChCkC,EAAAA,IAAC6B,EAAA,CAAmB,SAAA/D,EAAE,oBAAoB,CAAA,CAAE,CAAA,EAC9C,QACC,MAAA,CAAI,UAAU,yBACZ,SAAAF,GAAe,IAAKkE,GACnB9B,EAAAA,IAACI,EAAA,CAEC,KAAK,SACL,QAAQ,UACR,SAAUkB,EACV,QAAS,IAAM,KAAKE,EAAOM,EAAE,QAAQ,EAEpC,SAAAhE,EAAEgE,EAAE,OAAO,CAAA,EANPA,EAAE,QAAA,CAQV,EACH,QACCC,EAAA,CACC,SAAA/B,EAAAA,IAACI,EAAA,CACC,KAAK,SACL,QAAQ,YACR,SAAUkB,EACV,QAAS,IAAMC,EAAa,EAAK,EAEhC,SAAAzD,EAAE,iBAAkB,CAAE,GAAI,SAAU,CAAA,CAAA,CACvC,CACF,CAAA,CAAA,CACF,CAAA,CACF,CAEJ,CAEA,SAASmC,GAAW+B,EAAqB,CACvC,GAAI,CACF,MAAMC,EAAI,IAAI,KAAKD,CAAG,EACtB,GAAI,OAAO,MAAMC,EAAE,QAAA,CAAS,EAAG,OAAOD,EACtC,MAAME,MAAU,KAEhB,OADgBD,EAAE,aAAA,IAAmBC,EAAI,aAAA,EAEhCD,EAAE,mBAAmB,OAAW,CAAE,KAAM,UAAW,OAAQ,UAAW,EAExEA,EAAE,eAAe,OAAW,CAAE,MAAO,QAAS,IAAK,UAAW,KAAM,UAAW,OAAQ,SAAA,CAAW,CAC3G,MAAQ,CACN,OAAOD,CACT,CACF","x_google_ignoreList":[0]}
|
|
@@ -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 t=a("Save",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]);export{t as S};
|
|
7
|
-
//# sourceMappingURL=save-
|
|
7
|
+
//# sourceMappingURL=save-qwJa5_SA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"save-
|
|
1
|
+
{"version":3,"file":"save-qwJa5_SA.js","sources":["../../node_modules/lucide-react/dist/esm/icons/save.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 Save = createLucideIcon(\"Save\", [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n]);\n\nexport { Save as default };\n//# sourceMappingURL=save.js.map\n"],"names":["Save","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CACE,OACA,CACE,EAAG,qGACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,OAAQ,CAAE,EAAG,yBAA0B,IAAK,QAAQ,CAAE,CACzD,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{n as f,d as g,u as N,e as j,j as s,k as r,B as y,L as w,I as b}from"./index-
|
|
1
|
+
import{n as f,d as g,u as N,e as j,j as s,k as r,B as y,L as w,I as b}from"./index-DEWFfW_Z.js";import{r as C}from"./react-DlP5eolq.js";import{D as k}from"./data-table-DswkWUfG.js";import{E as v}from"./empty-state-D9Hi0Atm.js";import{u as R}from"./useQuery-CY2iazjN.js";import{L as S}from"./loader-circle-Bbw4pEyE.js";import{R as L}from"./refresh-ccw-uNKeBeRl.js";import"./table-BbAOSyc8.js";import"./arrow-up-BOADc9ce.js";import"./arrow-down-SLWKqtDc.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const M=f("CalendarClock",[["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",key:"1osxxc"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M3 10h5",key:"r794hk"}],["path",{d:"M17.5 17.5 16 16.3V14",key:"akvzfd"}],["circle",{cx:"16",cy:"16",r:"6",key:"qoo3c4"}]]),T={all:["schedules"],list:e=>["schedules","list",e]};function E(e){return R({queryKey:T.list(e),queryFn:()=>g.listSchedules(e)})}function V(){const{t:e}=N(["tasks","common"]),[t,i]=j(),l=t.get("agent")??"",{data:m,isLoading:o,isFetching:n,refetch:h}=E(l?{agent:l}:{}),u=m?.schedules??[];function x(a){const c=new URLSearchParams(t);a?c.set("agent",a):c.delete("agent"),i(c,{replace:!0})}const p=C.useMemo(()=>[{id:"id",header:e("schedules.col.id"),cell:a=>s.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",a.id]}),headClassName:"w-16"},{id:"name",header:e("schedules.col.name"),cell:a=>s.jsx("span",{className:"font-medium",children:a.name}),asCardTitle:!0},{id:"agent",header:e("schedules.col.agent"),cell:a=>s.jsx("span",{className:"text-text-dim",children:a.agent}),headClassName:"w-32"},{id:"cron",header:e("schedules.col.cron"),cell:a=>s.jsx("code",{className:"rounded bg-surface-2 px-1.5 py-0.5 text-xs",children:a.cron}),headClassName:"w-32"},{id:"prompt",header:e("schedules.col.prompt"),cell:a=>s.jsx("span",{className:"line-clamp-2 text-text-dim",children:a.prompt}),hideOnMobile:!0},{id:"enabled",header:e("schedules.col.enabled"),cell:a=>a.enabled?s.jsx(r,{variant:"success",children:e("schedules.enabled")}):s.jsx(r,{variant:"outline",children:e("schedules.disabled")}),headClassName:"w-20"},{id:"nextRun",header:e("schedules.col.nextRun"),cell:a=>s.jsx("span",{className:"text-text-dim",children:d(a.next_run)}),headClassName:"w-40"},{id:"lastRun",header:e("schedules.col.lastRun"),cell:a=>s.jsx("span",{className:"text-text-dim",children:d(a.last_run)}),headClassName:"w-40",hideOnMobile:!0}],[e]);return s.jsxs("div",{className:"mx-auto flex max-w-7xl flex-col gap-4",children:[s.jsxs("header",{className:"flex flex-col gap-1",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[s.jsx("h1",{className:"text-xl font-semibold",children:e("schedules.title")}),s.jsxs(y,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>h(),disabled:n,"aria-label":e("actions.refresh",{ns:"common"}),children:[n?s.jsx(S,{className:"h-4 w-4 animate-spin"}):s.jsx(L,{className:"h-4 w-4"}),s.jsx("span",{className:"hidden sm:inline",children:e("actions.refresh",{ns:"common"})})]})]}),s.jsx("p",{className:"text-sm text-text-dim",children:e("schedules.subtitle")})]}),s.jsx("div",{className:"flex flex-wrap items-end gap-2",children:s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsx(w,{htmlFor:"agent-filter",className:"text-xs text-text-dim",children:e("schedules.filter.agent")}),s.jsx(b,{id:"agent-filter",value:l,onChange:a=>x(a.target.value),placeholder:e("schedules.filter.agentAny"),className:"w-48"})]})}),s.jsx(k,{columns:p,rows:u,getRowId:a=>String(a.id),loading:o,emptyState:s.jsx(v,{icon:s.jsx(M,{}),title:e("schedules.empty.title"),description:e("schedules.empty.description")})})]})}function d(e){if(e==null)return"—";try{const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}export{V as default};
|
|
7
|
-
//# sourceMappingURL=schedules-
|
|
7
|
+
//# sourceMappingURL=schedules-Bcd0wbT4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedules-8mSjE14D.js","sources":["../../node_modules/lucide-react/dist/esm/icons/calendar-clock.js","../../src/hooks/use-schedules.ts","../../src/routes/tasks/schedules.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 CalendarClock = createLucideIcon(\"CalendarClock\", [\n [\"path\", { d: \"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5\", key: \"1osxxc\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M3 10h5\", key: \"r794hk\" }],\n [\"path\", { d: \"M17.5 17.5 16 16.3V14\", key: \"akvzfd\" }],\n [\"circle\", { cx: \"16\", cy: \"16\", r: \"6\", key: \"qoo3c4\" }]\n]);\n\nexport { CalendarClock as default };\n//# sourceMappingURL=calendar-clock.js.map\n","/**\n * useSchedules — react-query wrapper for /api/schedules.\n *\n * Read-only: schedule create / delete / toggle isn't exposed via\n * /api today (only via CLI). When that lands the mutations slot in\n * here next to useSchedules.\n */\n\nimport { useQueryClient, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { ListSchedulesQuery, ListSchedulesResponse } from '@/types/api'\n\nexport const schedulesKeys = {\n all: ['schedules'] as const,\n list: (q: ListSchedulesQuery) => ['schedules', 'list', q] as const,\n}\n\nexport function useSchedules(query: ListSchedulesQuery) {\n return useQuery<ListSchedulesResponse>({\n queryKey: schedulesKeys.list(query),\n queryFn: () => api.listSchedules(query),\n })\n}\n\nexport function useInvalidateSchedules() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: schedulesKeys.all })\n}\n","/**\n * /tasks/schedules — cron-style triggers list. Read-only; mutations\n * (create / delete / toggle) only exist via CLI today; the page\n * shows what's scheduled and when the next run lands.\n */\n\nimport { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { CalendarClock, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\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 { useSchedules } from '@/hooks/use-schedules'\nimport type { Schedule } from '@/types/api'\n\nexport default function SchedulesRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const agent = params.get('agent') ?? ''\n\n const { data, isLoading, isFetching, refetch } = useSchedules(\n agent ? { agent } : {},\n )\n const schedules = data?.schedules ?? []\n\n function setAgentFilter(v: string): void {\n const next = new URLSearchParams(params)\n if (!v) next.delete('agent')\n else next.set('agent', v)\n setParams(next, { replace: true })\n }\n\n const columns: DataTableColumn<Schedule>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('schedules.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'name',\n header: t('schedules.col.name'),\n cell: (r) => <span className=\"font-medium\">{r.name}</span>,\n asCardTitle: true,\n },\n {\n id: 'agent',\n header: t('schedules.col.agent'),\n cell: (r) => <span className=\"text-text-dim\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'cron',\n header: t('schedules.col.cron'),\n cell: (r) => <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs\">{r.cron}</code>,\n headClassName: 'w-32',\n },\n {\n id: 'prompt',\n header: t('schedules.col.prompt'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.prompt}</span>,\n hideOnMobile: true,\n },\n {\n id: 'enabled',\n header: t('schedules.col.enabled'),\n cell: (r) =>\n r.enabled ? (\n <Badge variant=\"success\">{t('schedules.enabled')}</Badge>\n ) : (\n <Badge variant=\"outline\">{t('schedules.disabled')}</Badge>\n ),\n headClassName: 'w-20',\n },\n {\n id: 'nextRun',\n header: t('schedules.col.nextRun'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.next_run)}</span>,\n headClassName: 'w-40',\n },\n {\n id: 'lastRun',\n header: t('schedules.col.lastRun'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.last_run)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('schedules.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('schedules.subtitle')}</p>\n </header>\n\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"agent-filter\" className=\"text-xs text-text-dim\">\n {t('schedules.filter.agent')}\n </Label>\n <Input\n id=\"agent-filter\"\n value={agent}\n onChange={(e) => setAgentFilter(e.target.value)}\n placeholder={t('schedules.filter.agentAny')}\n className=\"w-48\"\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n rows={schedules}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<CalendarClock />}\n title={t('schedules.empty.title')}\n description={t('schedules.empty.description')}\n />\n }\n />\n </div>\n )\n}\n\nfunction formatTime(iso: string | undefined | null): string {\n if (iso == null) return '—'\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["CalendarClock","createLucideIcon","schedulesKeys","q","useSchedules","query","useQuery","api","SchedulesRoute","t","useTranslation","params","setParams","useSearchParams","agent","data","isLoading","isFetching","refetch","schedules","setAgentFilter","v","next","columns","useMemo","r","jsxs","jsx","Badge","formatTime","Button","Loader2","RefreshCcw","Label","Input","e","DataTable","EmptyState","iso","d"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"schedules-Bcd0wbT4.js","sources":["../../node_modules/lucide-react/dist/esm/icons/calendar-clock.js","../../src/hooks/use-schedules.ts","../../src/routes/tasks/schedules.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 CalendarClock = createLucideIcon(\"CalendarClock\", [\n [\"path\", { d: \"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5\", key: \"1osxxc\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M3 10h5\", key: \"r794hk\" }],\n [\"path\", { d: \"M17.5 17.5 16 16.3V14\", key: \"akvzfd\" }],\n [\"circle\", { cx: \"16\", cy: \"16\", r: \"6\", key: \"qoo3c4\" }]\n]);\n\nexport { CalendarClock as default };\n//# sourceMappingURL=calendar-clock.js.map\n","/**\n * useSchedules — react-query wrapper for /api/schedules.\n *\n * Read-only: schedule create / delete / toggle isn't exposed via\n * /api today (only via CLI). When that lands the mutations slot in\n * here next to useSchedules.\n */\n\nimport { useQueryClient, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { ListSchedulesQuery, ListSchedulesResponse } from '@/types/api'\n\nexport const schedulesKeys = {\n all: ['schedules'] as const,\n list: (q: ListSchedulesQuery) => ['schedules', 'list', q] as const,\n}\n\nexport function useSchedules(query: ListSchedulesQuery) {\n return useQuery<ListSchedulesResponse>({\n queryKey: schedulesKeys.list(query),\n queryFn: () => api.listSchedules(query),\n })\n}\n\nexport function useInvalidateSchedules() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: schedulesKeys.all })\n}\n","/**\n * /tasks/schedules — cron-style triggers list. Read-only; mutations\n * (create / delete / toggle) only exist via CLI today; the page\n * shows what's scheduled and when the next run lands.\n */\n\nimport { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { CalendarClock, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\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 { useSchedules } from '@/hooks/use-schedules'\nimport type { Schedule } from '@/types/api'\n\nexport default function SchedulesRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const agent = params.get('agent') ?? ''\n\n const { data, isLoading, isFetching, refetch } = useSchedules(\n agent ? { agent } : {},\n )\n const schedules = data?.schedules ?? []\n\n function setAgentFilter(v: string): void {\n const next = new URLSearchParams(params)\n if (!v) next.delete('agent')\n else next.set('agent', v)\n setParams(next, { replace: true })\n }\n\n const columns: DataTableColumn<Schedule>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('schedules.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'name',\n header: t('schedules.col.name'),\n cell: (r) => <span className=\"font-medium\">{r.name}</span>,\n asCardTitle: true,\n },\n {\n id: 'agent',\n header: t('schedules.col.agent'),\n cell: (r) => <span className=\"text-text-dim\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'cron',\n header: t('schedules.col.cron'),\n cell: (r) => <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs\">{r.cron}</code>,\n headClassName: 'w-32',\n },\n {\n id: 'prompt',\n header: t('schedules.col.prompt'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.prompt}</span>,\n hideOnMobile: true,\n },\n {\n id: 'enabled',\n header: t('schedules.col.enabled'),\n cell: (r) =>\n r.enabled ? (\n <Badge variant=\"success\">{t('schedules.enabled')}</Badge>\n ) : (\n <Badge variant=\"outline\">{t('schedules.disabled')}</Badge>\n ),\n headClassName: 'w-20',\n },\n {\n id: 'nextRun',\n header: t('schedules.col.nextRun'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.next_run)}</span>,\n headClassName: 'w-40',\n },\n {\n id: 'lastRun',\n header: t('schedules.col.lastRun'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.last_run)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('schedules.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('schedules.subtitle')}</p>\n </header>\n\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"agent-filter\" className=\"text-xs text-text-dim\">\n {t('schedules.filter.agent')}\n </Label>\n <Input\n id=\"agent-filter\"\n value={agent}\n onChange={(e) => setAgentFilter(e.target.value)}\n placeholder={t('schedules.filter.agentAny')}\n className=\"w-48\"\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n rows={schedules}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<CalendarClock />}\n title={t('schedules.empty.title')}\n description={t('schedules.empty.description')}\n />\n }\n />\n </div>\n )\n}\n\nfunction formatTime(iso: string | undefined | null): string {\n if (iso == null) return '—'\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["CalendarClock","createLucideIcon","schedulesKeys","q","useSchedules","query","useQuery","api","SchedulesRoute","t","useTranslation","params","setParams","useSearchParams","agent","data","isLoading","isFetching","refetch","schedules","setAgentFilter","v","next","columns","useMemo","r","jsxs","jsx","Badge","formatTime","Button","Loader2","RefreshCcw","Label","Input","e","DataTable","EmptyState","iso","d"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as T,u as E,j as e,B as g,k as j,l as v,L as D,I}from"./index-
|
|
1
|
+
import{n as T,u as E,j as e,B as g,k as j,l as v,L as D,I}from"./index-DEWFfW_Z.js";import{r as w}from"./react-DlP5eolq.js";import{u as L,s as _,a as z,t as F}from"./use-settings-i1MhlkyC.js";import{L as K}from"./loader-circle-Bbw4pEyE.js";import{R as U}from"./refresh-ccw-uNKeBeRl.js";import{X as M}from"./x-D1iSuoqg.js";import{S as V}from"./save-qwJa5_SA.js";import{A as q}from"./arrow-up-BOADc9ce.js";import{A as J}from"./arrow-down-SLWKqtDc.js";import{C as W}from"./circle-check-8dbL-u7O.js";import{C as G}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 T,u as E,j as e,B as g,k as j,l as v,L as D,I}from"./index-O0BQoyzo.
|
|
|
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 Y=T("Key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]]);function Z(r,a){const o=(r??"").split(",").map(i=>i.trim()).filter(Boolean),h=new Set(a.map(i=>i.name)),m=new Set,x=[];for(const i of o)!h.has(i)||m.has(i)||(x.push({name:i,enabled:!0}),m.add(i));for(const i of a)m.has(i.name)||x.push({name:i.name,enabled:!1});return x}function B(r){return r.filter(a=>a.enabled).map(a=>a.name).join(",")}function ue(){const{t:r}=E(["settings","common"]),a=L({reveal:!1}),o=_(),h=z(),m=F(),x=a.data?.env??{},i=o.data?.providers??[],y=o.data?.chain??[],d=w.useMemo(()=>({chain:Z(x.IMHUB_WEB_SEARCH_PROVIDERS,i),keys:{},keysTouched:{}}),[x.IMHUB_WEB_SEARCH_PROVIDERS,i]),[l,u]=w.useState(d),[b,C]=w.useState("");w.useEffect(()=>{const s=JSON.stringify(d);s!==b&&(u(d),C(s))},[d,b]);const k=JSON.stringify(l.chain)!==JSON.stringify(d.chain)||Object.keys(l.keysTouched).length>0;function N(s,t){u(c=>{const n=[...c.chain],f=s+t;return f<0||f>=n.length?c:([n[s],n[f]]=[n[f],n[s]],{...c,chain:n})})}function S(s,t){u(c=>{const n=[...c.chain];return n[s]={...n[s],enabled:t},{...c,chain:n}})}function p(s,t){u(c=>({...c,keys:{...c.keys,[s]:t},keysTouched:{...c.keysTouched,[s]:!0}}))}function P(s){u(t=>({...t,keys:{...t.keys,[s]:""},keysTouched:{...t.keysTouched,[s]:!0}}))}async function A(){const s={},t=B(l.chain),c=B(d.chain);t!==c&&(s.IMHUB_WEB_SEARCH_PROVIDERS=t||null);for(const[n,f]of Object.entries(l.keysTouched)){if(!f)continue;const R=l.keys[n]??"";s[n]=R.trim()===""?null:R}if(Object.keys(s).length!==0)try{await h.mutateAsync({updates:s}),o.refetch(),v.success(r("search.savedToast")),u(n=>({...n,keys:{},keysTouched:{}}))}catch(n){v.error(n?.message??String(n))}}function H(){u(d)}async function O(s){try{const t=await m.mutateAsync({provider:s,query:"agim ping"});t.ok?v.success(r("search.testOk",{provider:s,hits:t.hits,ms:t.latencyMs})):v.error(r("search.testFail",{provider:s,error:t.error??"unknown error"}))}catch(t){v.error(t?.message??String(t))}}return e.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-6",children:[e.jsxs("header",{className:"flex items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:r("search.title")}),e.jsxs(g,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{a.refetch(),o.refetch()},disabled:a.isFetching||o.isFetching,"aria-label":r("actions.refresh",{ns:"common"}),children:[a.isFetching||o.isFetching?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(U,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:r("search.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:r("search.subtitle")}),e.jsx($,{live:y}),a.isLoading||o.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsx("section",{className:"flex flex-col gap-2",children:l.chain.map((s,t)=>{const c=i.find(n=>n.name===s.name);return e.jsx(ee,{info:c,entry:s,idx:t,count:l.chain.length,keyValue:c?.envKey?l.keys[c.envKey]:void 0,keyTouched:c?.envKey?!!l.keysTouched[c.envKey]:!1,onMove:n=>N(t,n),onToggle:n=>S(t,n),onSetKey:n=>c?.envKey&&p(c.envKey,n),onClearKey:()=>c?.envKey&&P(c.envKey),onTest:()=>O(s.name),testing:m.isPending},s.name)})}),k&&e.jsxs("div",{className:"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow",children:[e.jsx(j,{variant:"info",children:r("search.unsaved")}),e.jsxs(g,{variant:"ghost",size:"sm",className:"ml-auto",onClick:H,disabled:h.isPending,children:[e.jsx(M,{className:"h-4 w-4"})," ",r("search.discard")]}),e.jsxs(g,{size:"sm",onClick:()=>void A(),disabled:h.isPending,children:[h.isPending?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(V,{className:"h-4 w-4"}),r("search.save")]})]})]})}function $({live:r}){const{t:a}=E("settings");return e.jsxs("section",{className:"rounded-md border border-border bg-surface px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(X,{className:"h-4 w-4 text-text-dim"}),e.jsx("span",{className:"text-text-dim",children:a("search.chainLabel")}),r.length===0?e.jsx(j,{variant:"outline",children:a("search.chainEmpty")}):e.jsx("span",{className:"font-mono text-xs",children:r.join(" → ")})]}),e.jsx("p",{className:"mt-1 text-[11px] text-text-dim",children:a("search.chainHint")})]})}function ee(r){const{t:a}=E("settings"),{info:o,entry:h,idx:m,count:x,keyValue:i,keyTouched:y,onMove:d,onToggle:l,onSetKey:u,onClearKey:b,onTest:C,testing:k}=r,N=!!o?.envKey,S=!!o?.available||y&&!!i;return e.jsxs("div",{className:"rounded-md border border-border bg-surface p-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{className:"flex flex-col",children:[e.jsx("button",{type:"button",className:"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30",onClick:()=>d(-1),disabled:m===0,"aria-label":a("search.moveUp"),children:e.jsx(q,{className:"h-4 w-4"})}),e.jsx("button",{type:"button",className:"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30",onClick:()=>d(1),disabled:m===x-1,"aria-label":a("search.moveDown"),children:e.jsx(J,{className:"h-4 w-4"})})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:h.enabled,onChange:p=>l(p.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{className:"font-mono text-sm",children:h.name})]}),N?S?e.jsxs(j,{variant:"success",children:[e.jsx(W,{className:"mr-1 h-3 w-3"})," ",a("search.configured")]}):e.jsxs(j,{variant:"warning",children:[e.jsx(G,{className:"mr-1 h-3 w-3"})," ",a("search.missingKey")]}):e.jsx(j,{variant:"outline",children:a("search.noKey")}),e.jsx("div",{className:"ml-auto flex items-center gap-1",children:e.jsxs(g,{size:"sm",variant:"ghost",onClick:C,disabled:k||!h.enabled,"aria-label":a("search.testBtn"),children:[k?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(Q,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("search.testBtn")})]})})]}),N&&e.jsxs("div",{className:"mt-3 flex flex-col gap-1",children:[e.jsxs(D,{className:"text-xs font-medium",children:[e.jsx(Y,{className:"mr-1 inline h-3 w-3"}),o?.envKey]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(I,{type:"password",value:i??"",onChange:p=>u(p.target.value),placeholder:o?.available&&!y?a("search.placeholderConfigured"):a("search.placeholderEnter"),className:"font-mono text-xs"}),o?.available&&!y&&e.jsx(g,{size:"sm",variant:"ghost",onClick:b,"aria-label":a("search.clearKey"),children:e.jsx(M,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-[11px] text-text-dim",children:a("search.keyHint",{envKey:o?.envKey})})]})]})}export{ue as default};
|
|
17
|
-
//# sourceMappingURL=search-
|
|
17
|
+
//# sourceMappingURL=search-BUlzNWrj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-Con69NhG.js","sources":["../../node_modules/lucide-react/dist/esm/icons/flask-conical.js","../../node_modules/lucide-react/dist/esm/icons/globe.js","../../node_modules/lucide-react/dist/esm/icons/key.js","../../src/routes/settings/search.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 FlaskConical = createLucideIcon(\"FlaskConical\", [\n [\n \"path\",\n {\n d: \"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2\",\n key: \"18mbvz\"\n }\n ],\n [\"path\", { d: \"M6.453 15h11.094\", key: \"3shlmq\" }],\n [\"path\", { d: \"M8.5 2h7\", key: \"csnxdl\" }]\n]);\n\nexport { FlaskConical as default };\n//# sourceMappingURL=flask-conical.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 Globe = createLucideIcon(\"Globe\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.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 Key = createLucideIcon(\"Key\", [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n]);\n\nexport { Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * /settings/search — web_search provider config (v1.2.126).\n *\n * One row per registered provider (Tavily / Brave / Serper / Exa /\n * DuckDuckGo / Metaso): API-key input (masked-by-default), enable\n * toggle (= \"is this name in the chain?\"), reorder via up / down,\n * one-shot test button. The chain preview at the top shows what\n * IMHUB_WEB_SEARCH_PROVIDERS resolves to right now.\n *\n * Persistence: API keys go via PUT /api/env (which masks GET +\n * refuses echoed masks on PUT); the chain order is a single CSV\n * env key — same endpoint. Save is one round-trip per dirty key.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n ArrowDown, ArrowUp, CheckCircle2, FlaskConical, Globe, Key,\n Loader2, RefreshCcw, Save, 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 useEnv,\n useSearchProviders,\n useTestSearchProvider,\n useUpdateEnv,\n} from '@/hooks/use-settings'\nimport type { SearchProviderInfo } from '@/types/api'\n\ninterface ChainEntry {\n name: string\n enabled: boolean\n}\n\ninterface Draft {\n /** Provider chain — every known provider, with `enabled`\n * reflecting \"is name in the CSV\". Order is the row order. */\n chain: ChainEntry[]\n /** Each provider's API-key input. Keyed by envKey (e.g.\n * TAVILY_API_KEY). Holds either '' (clear) or the new plaintext\n * the operator typed. We never load values back from the server. */\n keys: Record<string, string>\n /** Tracks which key fields the operator actually touched — so\n * Save only sends the diff and untouched masked keys are left\n * alone. */\n keysTouched: Record<string, boolean>\n}\n\nfunction envChainOrder(envValue: string | undefined, providers: SearchProviderInfo[]): ChainEntry[] {\n // Parse the CSV chain; preserve operator order; tail-append any\n // provider not in the CSV as disabled so they remain renderable.\n const raw = (envValue ?? '').split(',').map((s) => s.trim()).filter(Boolean)\n const known = new Set(providers.map((p) => p.name))\n const seen = new Set<string>()\n const out: ChainEntry[] = []\n for (const name of raw) {\n if (!known.has(name) || seen.has(name)) continue\n out.push({ name, enabled: true })\n seen.add(name)\n }\n for (const p of providers) {\n if (seen.has(p.name)) continue\n out.push({ name: p.name, enabled: false })\n }\n return out\n}\n\nfunction chainToCsv(chain: ChainEntry[]): string {\n return chain.filter((c) => c.enabled).map((c) => c.name).join(',')\n}\n\nexport default function SettingsSearchRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv({ reveal: false })\n const providersQuery = useSearchProviders()\n const updateEnv = useUpdateEnv()\n const testProvider = useTestSearchProvider()\n\n const envData = envQuery.data?.env ?? {}\n const providers = providersQuery.data?.providers ?? []\n const live = providersQuery.data?.chain ?? []\n\n const initial = useMemo<Draft>(\n () => ({\n chain: envChainOrder(envData.IMHUB_WEB_SEARCH_PROVIDERS, providers),\n keys: {},\n keysTouched: {},\n }),\n [envData.IMHUB_WEB_SEARCH_PROVIDERS, providers],\n )\n\n const [draft, setDraft] = useState<Draft>(initial)\n const [syncedHash, setSyncedHash] = useState('')\n\n useEffect(() => {\n const hash = JSON.stringify(initial)\n if (hash !== syncedHash) {\n setDraft(initial)\n setSyncedHash(hash)\n }\n }, [initial, syncedHash])\n\n const isDirty =\n JSON.stringify(draft.chain) !== JSON.stringify(initial.chain) ||\n Object.keys(draft.keysTouched).length > 0\n\n function moveRow(idx: number, delta: -1 | 1): void {\n setDraft((d) => {\n const next = [...d.chain]\n const swap = idx + delta\n if (swap < 0 || swap >= next.length) return d\n ;[next[idx], next[swap]] = [next[swap], next[idx]]\n return { ...d, chain: next }\n })\n }\n\n function toggleRow(idx: number, enabled: boolean): void {\n setDraft((d) => {\n const next = [...d.chain]\n next[idx] = { ...next[idx], enabled }\n return { ...d, chain: next }\n })\n }\n\n function setKey(envKey: string, value: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: value },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n function clearKey(envKey: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: '' },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n async function onSave(): Promise<void> {\n const updates: Record<string, string | null> = {}\n const nextCsv = chainToCsv(draft.chain)\n const initialCsv = chainToCsv(initial.chain)\n if (nextCsv !== initialCsv) {\n updates.IMHUB_WEB_SEARCH_PROVIDERS = nextCsv || null\n }\n for (const [envKey, touched] of Object.entries(draft.keysTouched)) {\n if (!touched) continue\n const v = draft.keys[envKey] ?? ''\n updates[envKey] = v.trim() === '' ? null : v\n }\n if (Object.keys(updates).length === 0) return\n try {\n await updateEnv.mutateAsync({ updates })\n // Refetch both — env keys changed availability, chain order changed.\n void providersQuery.refetch()\n toast.success(t('search.savedToast'))\n setDraft((d) => ({ ...d, keys: {}, keysTouched: {} }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n function onDiscard(): void {\n setDraft(initial)\n }\n\n async function onTest(provider: string): Promise<void> {\n try {\n const result = await testProvider.mutateAsync({\n provider,\n // Short, harmless probe — the dispatcher only needs to\n // verify the upstream auth + transport.\n query: 'agim ping',\n })\n if (result.ok) {\n toast.success(\n t('search.testOk', { provider, hits: result.hits, ms: result.latencyMs }),\n )\n } else {\n toast.error(\n t('search.testFail', { provider, error: result.error ?? 'unknown error' }),\n )\n }\n } catch (err) {\n toast.error((err as Error)?.message ?? String(err))\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('search.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => {\n void envQuery.refetch()\n void providersQuery.refetch()\n }}\n disabled={envQuery.isFetching || providersQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || providersQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('search.subtitle')}</p>\n\n <ChainPreview live={live} />\n\n {envQuery.isLoading || providersQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <section className=\"flex flex-col gap-2\">\n {draft.chain.map((entry, idx) => {\n const info = providers.find((p) => p.name === entry.name)\n return (\n <ProviderRow\n key={entry.name}\n info={info}\n entry={entry}\n idx={idx}\n count={draft.chain.length}\n keyValue={info?.envKey ? draft.keys[info.envKey] : undefined}\n keyTouched={info?.envKey ? !!draft.keysTouched[info.envKey] : false}\n onMove={(d) => moveRow(idx, d)}\n onToggle={(v) => toggleRow(idx, v)}\n onSetKey={(v) => info?.envKey && setKey(info.envKey, v)}\n onClearKey={() => info?.envKey && clearKey(info.envKey)}\n onTest={() => onTest(entry.name)}\n testing={testProvider.isPending}\n />\n )\n })}\n </section>\n )}\n\n {isDirty && (\n <div className=\"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow\">\n <Badge variant=\"info\">{t('search.unsaved')}</Badge>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateEnv.isPending}\n >\n <X className=\"h-4 w-4\" /> {t('search.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 {t('search.save')}\n </Button>\n </div>\n )}\n </div>\n )\n}\n\nfunction ChainPreview({ live }: { live: string[] }): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm\">\n <Globe className=\"h-4 w-4 text-text-dim\" />\n <span className=\"text-text-dim\">{t('search.chainLabel')}</span>\n {live.length === 0 ? (\n <Badge variant=\"outline\">{t('search.chainEmpty')}</Badge>\n ) : (\n <span className=\"font-mono text-xs\">{live.join(' → ')}</span>\n )}\n </div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('search.chainHint')}</p>\n </section>\n )\n}\n\ninterface ProviderRowProps {\n info: SearchProviderInfo | undefined\n entry: ChainEntry\n idx: number\n count: number\n keyValue: string | undefined\n keyTouched: boolean\n onMove: (delta: -1 | 1) => void\n onToggle: (v: boolean) => void\n onSetKey: (v: string) => void\n onClearKey: () => void\n onTest: () => void\n testing: boolean\n}\n\nfunction ProviderRow(props: ProviderRowProps): JSX.Element {\n const { t } = useTranslation('settings')\n const { info, entry, idx, count, keyValue, keyTouched, onMove, onToggle,\n onSetKey, onClearKey, onTest, testing } = props\n const needsKey = !!info?.envKey\n const available = !!info?.available || (keyTouched && !!keyValue)\n return (\n <div className=\"rounded-md border border-border bg-surface p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex flex-col\">\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(-1)}\n disabled={idx === 0}\n aria-label={t('search.moveUp')}\n >\n <ArrowUp className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(1)}\n disabled={idx === count - 1}\n aria-label={t('search.moveDown')}\n >\n <ArrowDown className=\"h-4 w-4\" />\n </button>\n </div>\n\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={entry.enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n <span className=\"font-mono text-sm\">{entry.name}</span>\n </label>\n\n {!needsKey ? (\n <Badge variant=\"outline\">{t('search.noKey')}</Badge>\n ) : available ? (\n <Badge variant=\"success\">\n <CheckCircle2 className=\"mr-1 h-3 w-3\" /> {t('search.configured')}\n </Badge>\n ) : (\n <Badge variant=\"warning\">\n <XCircle className=\"mr-1 h-3 w-3\" /> {t('search.missingKey')}\n </Badge>\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onTest}\n disabled={testing || !entry.enabled}\n aria-label={t('search.testBtn')}\n >\n {testing\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <FlaskConical className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.testBtn')}</span>\n </Button>\n </div>\n </div>\n\n {needsKey && (\n <div className=\"mt-3 flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">\n <Key className=\"mr-1 inline h-3 w-3\" />\n {info?.envKey}\n </Label>\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"password\"\n value={keyValue ?? ''}\n onChange={(e) => onSetKey(e.target.value)}\n placeholder={\n info?.available && !keyTouched\n ? t('search.placeholderConfigured')\n : t('search.placeholderEnter')\n }\n className=\"font-mono text-xs\"\n />\n {info?.available && !keyTouched && (\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onClearKey}\n aria-label={t('search.clearKey')}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n <p className=\"text-[11px] text-text-dim\">\n {t('search.keyHint', { envKey: info?.envKey })}\n </p>\n </div>\n )}\n </div>\n )\n}\n"],"names":["FlaskConical","createLucideIcon","Globe","Key","envChainOrder","envValue","providers","raw","s","known","p","seen","out","name","chainToCsv","chain","c","SettingsSearchRoute","t","useTranslation","envQuery","useEnv","providersQuery","useSearchProviders","updateEnv","useUpdateEnv","testProvider","useTestSearchProvider","envData","live","initial","useMemo","draft","setDraft","useState","syncedHash","setSyncedHash","useEffect","hash","isDirty","moveRow","idx","delta","d","next","swap","toggleRow","enabled","setKey","envKey","value","clearKey","onSave","updates","nextCsv","initialCsv","touched","v","toast","err","onDiscard","onTest","provider","result","jsxs","jsx","Button","Loader2","RefreshCcw","ChainPreview","entry","info","ProviderRow","Badge","X","Save","props","count","keyValue","keyTouched","onMove","onToggle","onSetKey","onClearKey","testing","needsKey","available","ArrowUp","ArrowDown","e","CheckCircle2","XCircle","Label","Input"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
1
|
+
{"version":3,"file":"search-BUlzNWrj.js","sources":["../../node_modules/lucide-react/dist/esm/icons/flask-conical.js","../../node_modules/lucide-react/dist/esm/icons/globe.js","../../node_modules/lucide-react/dist/esm/icons/key.js","../../src/routes/settings/search.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 FlaskConical = createLucideIcon(\"FlaskConical\", [\n [\n \"path\",\n {\n d: \"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2\",\n key: \"18mbvz\"\n }\n ],\n [\"path\", { d: \"M6.453 15h11.094\", key: \"3shlmq\" }],\n [\"path\", { d: \"M8.5 2h7\", key: \"csnxdl\" }]\n]);\n\nexport { FlaskConical as default };\n//# sourceMappingURL=flask-conical.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 Globe = createLucideIcon(\"Globe\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.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 Key = createLucideIcon(\"Key\", [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n]);\n\nexport { Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * /settings/search — web_search provider config (v1.2.126).\n *\n * One row per registered provider (Tavily / Brave / Serper / Exa /\n * DuckDuckGo / Metaso): API-key input (masked-by-default), enable\n * toggle (= \"is this name in the chain?\"), reorder via up / down,\n * one-shot test button. The chain preview at the top shows what\n * IMHUB_WEB_SEARCH_PROVIDERS resolves to right now.\n *\n * Persistence: API keys go via PUT /api/env (which masks GET +\n * refuses echoed masks on PUT); the chain order is a single CSV\n * env key — same endpoint. Save is one round-trip per dirty key.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n ArrowDown, ArrowUp, CheckCircle2, FlaskConical, Globe, Key,\n Loader2, RefreshCcw, Save, 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 useEnv,\n useSearchProviders,\n useTestSearchProvider,\n useUpdateEnv,\n} from '@/hooks/use-settings'\nimport type { SearchProviderInfo } from '@/types/api'\n\ninterface ChainEntry {\n name: string\n enabled: boolean\n}\n\ninterface Draft {\n /** Provider chain — every known provider, with `enabled`\n * reflecting \"is name in the CSV\". Order is the row order. */\n chain: ChainEntry[]\n /** Each provider's API-key input. Keyed by envKey (e.g.\n * TAVILY_API_KEY). Holds either '' (clear) or the new plaintext\n * the operator typed. We never load values back from the server. */\n keys: Record<string, string>\n /** Tracks which key fields the operator actually touched — so\n * Save only sends the diff and untouched masked keys are left\n * alone. */\n keysTouched: Record<string, boolean>\n}\n\nfunction envChainOrder(envValue: string | undefined, providers: SearchProviderInfo[]): ChainEntry[] {\n // Parse the CSV chain; preserve operator order; tail-append any\n // provider not in the CSV as disabled so they remain renderable.\n const raw = (envValue ?? '').split(',').map((s) => s.trim()).filter(Boolean)\n const known = new Set(providers.map((p) => p.name))\n const seen = new Set<string>()\n const out: ChainEntry[] = []\n for (const name of raw) {\n if (!known.has(name) || seen.has(name)) continue\n out.push({ name, enabled: true })\n seen.add(name)\n }\n for (const p of providers) {\n if (seen.has(p.name)) continue\n out.push({ name: p.name, enabled: false })\n }\n return out\n}\n\nfunction chainToCsv(chain: ChainEntry[]): string {\n return chain.filter((c) => c.enabled).map((c) => c.name).join(',')\n}\n\nexport default function SettingsSearchRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv({ reveal: false })\n const providersQuery = useSearchProviders()\n const updateEnv = useUpdateEnv()\n const testProvider = useTestSearchProvider()\n\n const envData = envQuery.data?.env ?? {}\n const providers = providersQuery.data?.providers ?? []\n const live = providersQuery.data?.chain ?? []\n\n const initial = useMemo<Draft>(\n () => ({\n chain: envChainOrder(envData.IMHUB_WEB_SEARCH_PROVIDERS, providers),\n keys: {},\n keysTouched: {},\n }),\n [envData.IMHUB_WEB_SEARCH_PROVIDERS, providers],\n )\n\n const [draft, setDraft] = useState<Draft>(initial)\n const [syncedHash, setSyncedHash] = useState('')\n\n useEffect(() => {\n const hash = JSON.stringify(initial)\n if (hash !== syncedHash) {\n setDraft(initial)\n setSyncedHash(hash)\n }\n }, [initial, syncedHash])\n\n const isDirty =\n JSON.stringify(draft.chain) !== JSON.stringify(initial.chain) ||\n Object.keys(draft.keysTouched).length > 0\n\n function moveRow(idx: number, delta: -1 | 1): void {\n setDraft((d) => {\n const next = [...d.chain]\n const swap = idx + delta\n if (swap < 0 || swap >= next.length) return d\n ;[next[idx], next[swap]] = [next[swap], next[idx]]\n return { ...d, chain: next }\n })\n }\n\n function toggleRow(idx: number, enabled: boolean): void {\n setDraft((d) => {\n const next = [...d.chain]\n next[idx] = { ...next[idx], enabled }\n return { ...d, chain: next }\n })\n }\n\n function setKey(envKey: string, value: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: value },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n function clearKey(envKey: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: '' },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n async function onSave(): Promise<void> {\n const updates: Record<string, string | null> = {}\n const nextCsv = chainToCsv(draft.chain)\n const initialCsv = chainToCsv(initial.chain)\n if (nextCsv !== initialCsv) {\n updates.IMHUB_WEB_SEARCH_PROVIDERS = nextCsv || null\n }\n for (const [envKey, touched] of Object.entries(draft.keysTouched)) {\n if (!touched) continue\n const v = draft.keys[envKey] ?? ''\n updates[envKey] = v.trim() === '' ? null : v\n }\n if (Object.keys(updates).length === 0) return\n try {\n await updateEnv.mutateAsync({ updates })\n // Refetch both — env keys changed availability, chain order changed.\n void providersQuery.refetch()\n toast.success(t('search.savedToast'))\n setDraft((d) => ({ ...d, keys: {}, keysTouched: {} }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n function onDiscard(): void {\n setDraft(initial)\n }\n\n async function onTest(provider: string): Promise<void> {\n try {\n const result = await testProvider.mutateAsync({\n provider,\n // Short, harmless probe — the dispatcher only needs to\n // verify the upstream auth + transport.\n query: 'agim ping',\n })\n if (result.ok) {\n toast.success(\n t('search.testOk', { provider, hits: result.hits, ms: result.latencyMs }),\n )\n } else {\n toast.error(\n t('search.testFail', { provider, error: result.error ?? 'unknown error' }),\n )\n }\n } catch (err) {\n toast.error((err as Error)?.message ?? String(err))\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('search.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => {\n void envQuery.refetch()\n void providersQuery.refetch()\n }}\n disabled={envQuery.isFetching || providersQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || providersQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('search.subtitle')}</p>\n\n <ChainPreview live={live} />\n\n {envQuery.isLoading || providersQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <section className=\"flex flex-col gap-2\">\n {draft.chain.map((entry, idx) => {\n const info = providers.find((p) => p.name === entry.name)\n return (\n <ProviderRow\n key={entry.name}\n info={info}\n entry={entry}\n idx={idx}\n count={draft.chain.length}\n keyValue={info?.envKey ? draft.keys[info.envKey] : undefined}\n keyTouched={info?.envKey ? !!draft.keysTouched[info.envKey] : false}\n onMove={(d) => moveRow(idx, d)}\n onToggle={(v) => toggleRow(idx, v)}\n onSetKey={(v) => info?.envKey && setKey(info.envKey, v)}\n onClearKey={() => info?.envKey && clearKey(info.envKey)}\n onTest={() => onTest(entry.name)}\n testing={testProvider.isPending}\n />\n )\n })}\n </section>\n )}\n\n {isDirty && (\n <div className=\"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow\">\n <Badge variant=\"info\">{t('search.unsaved')}</Badge>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateEnv.isPending}\n >\n <X className=\"h-4 w-4\" /> {t('search.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 {t('search.save')}\n </Button>\n </div>\n )}\n </div>\n )\n}\n\nfunction ChainPreview({ live }: { live: string[] }): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm\">\n <Globe className=\"h-4 w-4 text-text-dim\" />\n <span className=\"text-text-dim\">{t('search.chainLabel')}</span>\n {live.length === 0 ? (\n <Badge variant=\"outline\">{t('search.chainEmpty')}</Badge>\n ) : (\n <span className=\"font-mono text-xs\">{live.join(' → ')}</span>\n )}\n </div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('search.chainHint')}</p>\n </section>\n )\n}\n\ninterface ProviderRowProps {\n info: SearchProviderInfo | undefined\n entry: ChainEntry\n idx: number\n count: number\n keyValue: string | undefined\n keyTouched: boolean\n onMove: (delta: -1 | 1) => void\n onToggle: (v: boolean) => void\n onSetKey: (v: string) => void\n onClearKey: () => void\n onTest: () => void\n testing: boolean\n}\n\nfunction ProviderRow(props: ProviderRowProps): JSX.Element {\n const { t } = useTranslation('settings')\n const { info, entry, idx, count, keyValue, keyTouched, onMove, onToggle,\n onSetKey, onClearKey, onTest, testing } = props\n const needsKey = !!info?.envKey\n const available = !!info?.available || (keyTouched && !!keyValue)\n return (\n <div className=\"rounded-md border border-border bg-surface p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex flex-col\">\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(-1)}\n disabled={idx === 0}\n aria-label={t('search.moveUp')}\n >\n <ArrowUp className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(1)}\n disabled={idx === count - 1}\n aria-label={t('search.moveDown')}\n >\n <ArrowDown className=\"h-4 w-4\" />\n </button>\n </div>\n\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={entry.enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n <span className=\"font-mono text-sm\">{entry.name}</span>\n </label>\n\n {!needsKey ? (\n <Badge variant=\"outline\">{t('search.noKey')}</Badge>\n ) : available ? (\n <Badge variant=\"success\">\n <CheckCircle2 className=\"mr-1 h-3 w-3\" /> {t('search.configured')}\n </Badge>\n ) : (\n <Badge variant=\"warning\">\n <XCircle className=\"mr-1 h-3 w-3\" /> {t('search.missingKey')}\n </Badge>\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onTest}\n disabled={testing || !entry.enabled}\n aria-label={t('search.testBtn')}\n >\n {testing\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <FlaskConical className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.testBtn')}</span>\n </Button>\n </div>\n </div>\n\n {needsKey && (\n <div className=\"mt-3 flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">\n <Key className=\"mr-1 inline h-3 w-3\" />\n {info?.envKey}\n </Label>\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"password\"\n value={keyValue ?? ''}\n onChange={(e) => onSetKey(e.target.value)}\n placeholder={\n info?.available && !keyTouched\n ? t('search.placeholderConfigured')\n : t('search.placeholderEnter')\n }\n className=\"font-mono text-xs\"\n />\n {info?.available && !keyTouched && (\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onClearKey}\n aria-label={t('search.clearKey')}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n <p className=\"text-[11px] text-text-dim\">\n {t('search.keyHint', { envKey: info?.envKey })}\n </p>\n </div>\n )}\n </div>\n )\n}\n"],"names":["FlaskConical","createLucideIcon","Globe","Key","envChainOrder","envValue","providers","raw","s","known","p","seen","out","name","chainToCsv","chain","c","SettingsSearchRoute","t","useTranslation","envQuery","useEnv","providersQuery","useSearchProviders","updateEnv","useUpdateEnv","testProvider","useTestSearchProvider","envData","live","initial","useMemo","draft","setDraft","useState","syncedHash","setSyncedHash","useEffect","hash","isDirty","moveRow","idx","delta","d","next","swap","toggleRow","enabled","setKey","envKey","value","clearKey","onSave","updates","nextCsv","initialCsv","touched","v","toast","err","onDiscard","onTest","provider","result","jsxs","jsx","Button","Loader2","RefreshCcw","ChainPreview","entry","info","ProviderRow","Badge","X","Save","props","count","keyValue","keyTouched","onMove","onToggle","onSetKey","onClearKey","testing","needsKey","available","ArrowUp","ArrowDown","e","CheckCircle2","XCircle","Label","Input"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
@@ -1,7 +1,7 @@
|
|
|
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.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const r=e("Search",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]);export{r as S};
|
|
7
|
-
//# sourceMappingURL=search-
|
|
7
|
+
//# sourceMappingURL=search-i1tP2maJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-
|
|
1
|
+
{"version":3,"file":"search-i1tP2maJ.js","sources":["../../node_modules/lucide-react/dist/esm/icons/search.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 Search = createLucideIcon(\"Search\", [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"path\", { d: \"m21 21-4.3-4.3\", key: \"1qie3q\" }]\n]);\n\nexport { Search as default };\n//# sourceMappingURL=search.js.map\n"],"names":["Search","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as N,j as e,B as I,I as d,S as h,f as _,g as f,h as p,i as u,o as T,l as j,m as E,p as M,c as w,k as U}from"./index-
|
|
2
|
-
//# sourceMappingURL=security-
|
|
1
|
+
import{u as N,j as e,B as I,I as d,S as h,f as _,g as f,h as p,i as u,o as T,l as j,m as E,p as M,c as w,k as U}from"./index-DEWFfW_Z.js";import{r as v}from"./react-DlP5eolq.js";import{u as S,a as L}from"./use-settings-i1MhlkyC.js";import{L as C}from"./loader-circle-Bbw4pEyE.js";import{R as O}from"./refresh-ccw-uNKeBeRl.js";import{S as H}from"./shield-alert-DrnN6fz_.js";import{C as R}from"./circle-check-8dbL-u7O.js";import"./useQuery-CY2iazjN.js";function V(s){if(s==null)return!1;const a=s.toLowerCase();return a==="1"||a==="true"||a==="yes"||a==="on"}function $(){const{t:s}=N(["settings","common"]),a=S(),o=L(),[i,B]=v.useState(null),[b,y]=v.useState(!1);async function g(){y(!0);try{const t=await T.get("/api/security/diagnostics");B(t.diagnostics)}catch(t){j.error(E(t,s).message)}finally{y(!1)}}v.useEffect(()=>{g()},[]);async function r(t,l){try{await o.mutateAsync({updates:{[t]:l}}),j.success(s("security.savingToast")),await g()}catch(A){j.error(E(A,s).message)}}const n=a.data?.env??{};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("security.title")}),e.jsx(I,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{a.refetch(),g()},disabled:a.isFetching||b,"aria-label":s("actions.refresh",{ns:"common"}),children:a.isFetching||b?e.jsx(C,{className:"h-4 w-4 animate-spin"}):e.jsx(O,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-sm text-muted",children:s("security.subtitle")})]}),e.jsxs("section",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("h2",{className:"mb-3 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(H,{className:"h-4 w-4"}),s("security.diagnostics.title")]}),i?e.jsxs("ul",{className:"grid gap-2 text-sm sm:grid-cols-2",children:[e.jsx(x,{label:s("security.diagnostics.runningAsRoot"),ok:i.runningAsRoot===!1,text:i.runningAsRoot===!0?s("security.diagnostics.runningAsRootHelp"):"OK"}),e.jsx(x,{label:s("security.diagnostics.envFilePerms"),ok:i.envFile.exists&&!i.envFile.tooPermissive,text:i.envFile.exists?i.envFile.tooPermissive?`${i.envFile.mode} — ${s("security.diagnostics.envFilePermsLax")}`:s("security.diagnostics.envFilePermsOk"):"—"}),e.jsx(x,{label:s("security.diagnostics.bwrapAvailable"),ok:i.bwrapAvailable,text:i.bwrapAvailable?"/usr/bin/bwrap":s("security.diagnostics.bwrapMissing")}),e.jsx(x,{label:s("security.diagnostics.senderAllowlist"),ok:i.senderAllowlistConfigured,text:i.senderAllowlistConfigured?s("security.diagnostics.senderAllowlistOn"):s("security.diagnostics.senderAllowlistOff")}),e.jsx(x,{label:s("security.diagnostics.adminAllowlist"),ok:i.adminAllowlistConfigured,text:i.adminAllowlistConfigured?s("security.diagnostics.adminAllowlistOn"):s("security.diagnostics.adminAllowlistOff")}),e.jsx(x,{label:s("security.diagnosticsPlatformBlacklist"),ok:i.platformBlacklist.length===0,text:i.platformBlacklist.length===0?"—":i.platformBlacklist.join(", ")})]}):e.jsx("p",{className:"text-sm text-muted",children:"…"})]}),e.jsx(m,{title:s("security.sender.title"),description:s("security.sender.description"),envKey:"IMHUB_ALLOWED_USERS",children:e.jsx(d,{defaultValue:n.IMHUB_ALLOWED_USERS??"",placeholder:s("security.sender.placeholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_ALLOWED_USERS",l===""?null:l)}})}),e.jsx(m,{title:s("security.exec.title"),description:s("security.exec.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.exec.sandbox"),children:e.jsxs(h,{value:(n.IMHUB_EXEC_SANDBOX??"").toLowerCase()==="bwrap"?"bwrap":"__none__",onValueChange:t=>void r("IMHUB_EXEC_SANDBOX",t==="__none__"?null:t),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"__none__",children:s("security.exec.sandboxNone")}),e.jsxs(u,{value:"bwrap",disabled:!i?.bwrapAvailable,children:[s("security.exec.sandboxBwrap"),!i?.bwrapAvailable&&e.jsxs("span",{className:"ml-2 text-xs text-muted",children:["(",s("security.exec.sandboxBwrapMissing"),")"]})]})]})]})}),e.jsx(c,{label:s("security.exec.sandboxNet"),children:e.jsxs(h,{value:(n.IMHUB_EXEC_SANDBOX_NET??"").toLowerCase()==="off"?"off":"on",onValueChange:t=>void r("IMHUB_EXEC_SANDBOX_NET",t==="off"?"off":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"on",children:s("security.exec.sandboxNetOn")}),e.jsx(u,{value:"off",children:s("security.exec.sandboxNetOff")})]})]})}),e.jsx(c,{label:s("security.exec.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_EXEC_TIMEOUT_MS??"",placeholder:"60000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_EXEC_TIMEOUT_MS",l===""?null:l)}})}),e.jsx(c,{label:s("security.exec.maxOutput"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_EXEC_MAX_OUTPUT??"",placeholder:"32768",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_EXEC_MAX_OUTPUT",l===""?null:l)}})})]})}),e.jsx(m,{title:s("security.web.title"),description:s("security.web.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.web.allowPrivate"),hint:s("security.web.allowPrivateHelp"),children:e.jsxs(h,{value:V(n.IMHUB_NATIVE_WEB_ALLOW_PRIVATE)?"1":"0",onValueChange:t=>void r("IMHUB_NATIVE_WEB_ALLOW_PRIVATE",t==="1"?"1":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"0",children:"OFF"}),e.jsx(u,{value:"1",children:"ON"})]})]})}),e.jsx(c,{label:s("security.web.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_WEB_TIMEOUT_MS??"",placeholder:"30000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_WEB_TIMEOUT_MS",l===""?null:l)}})}),e.jsx("div",{className:"sm:col-span-2",children:e.jsx(c,{label:s("security.web.ssrfWhitelist"),children:e.jsx(d,{defaultValue:n.IMHUB_NATIVE_WEB_SSRF_WHITELIST??"",placeholder:s("security.web.ssrfWhitelistPlaceholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_WEB_SSRF_WHITELIST",l===""?null:l)}})})})]})}),e.jsx(m,{title:s("security.fs.title"),description:s("security.fs.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.fs.restrict"),children:e.jsxs(h,{value:(n.IMHUB_NATIVE_FS_RESTRICT??"1")==="0"?"0":"1",onValueChange:t=>void r("IMHUB_NATIVE_FS_RESTRICT",t==="0"?"0":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"1",children:s("security.fs.restrictOn")}),e.jsx(u,{value:"0",children:s("security.fs.restrictOff")})]})]})}),e.jsx(c,{label:s("security.fs.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_FS_TIMEOUT_MS??"",placeholder:"60000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_FS_TIMEOUT_MS",l===""?null:l)}})})]})}),e.jsx(m,{title:s("security.delegation.title"),description:s("security.delegation.description"),envKey:"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN",children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN??"",placeholder:"2",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN",l===""?null:l)}})}),e.jsxs(m,{title:s("security.platformBlacklist.title"),description:s("security.platformBlacklist.description"),envKey:"IMHUB_PLATFORM_BLACKLIST",children:[e.jsx(d,{defaultValue:n.IMHUB_PLATFORM_BLACKLIST??"",placeholder:s("security.platformBlacklist.placeholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_PLATFORM_BLACKLIST",l===""?null:l)}}),i?.platformBlacklist&&i.platformBlacklist.length>0&&e.jsxs("p",{className:"mt-2 text-[10px] text-muted",children:[s("security.platformBlacklist.currentLabel"),": ",i.platformBlacklist.join(", ")]})]})]})}function x({label:s,ok:a,text:o}){return e.jsxs("li",{className:"flex items-start gap-2",children:[a?e.jsx(R,{className:"mt-0.5 h-4 w-4 shrink-0 text-success"}):e.jsx(M,{className:"mt-0.5 h-4 w-4 shrink-0 text-warning"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"font-medium",children:s}),e.jsx("div",{className:w("text-xs",a?"text-muted":"text-warning"),children:o})]})]})}function m({title:s,description:a,envKey:o,children:i}){return e.jsxs("section",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("div",{className:"mb-2 flex flex-wrap items-baseline gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold",children:s}),o&&e.jsx(U,{variant:"outline",className:"font-mono text-[10px]",children:o})]}),e.jsx("p",{className:"mb-3 text-xs text-muted",children:a}),i]})}function c({label:s,hint:a,children:o}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-xs font-medium text-muted",children:s}),o,a&&e.jsx("p",{className:"text-[10px] text-muted",children:a})]})}export{$ as default};
|
|
2
|
+
//# sourceMappingURL=security-DgJyTT4g.js.map
|