foxclaw 0.1.0 → 0.1.3
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/README.md +54 -29
- package/bin/foxclaw.cjs +51 -0
- package/index.js +4 -10
- package/package.json +46 -38
- package/python/.dockerignore +35 -0
- package/python/.env.example +173 -0
- package/python/.gitattributes +46 -0
- package/python/.github/workflows/ci.yml +167 -0
- package/python/.github/workflows/release.yml +183 -0
- package/python/CHANGELOG.md +57 -0
- package/python/CHANGELOG_CN.md +57 -0
- package/python/Dockerfile +64 -0
- package/python/LICENSE +21 -0
- package/python/MANIFEST.in +14 -0
- package/python/README.md +201 -0
- package/python/README_CN.md +336 -0
- package/python/bench/bm25_audit.py +186 -0
- package/python/bench/bm25_regression.py +177 -0
- package/python/bench/bm25_stress.py +155 -0
- package/python/bench/cd_audit.py +215 -0
- package/python/bench/chaos.py +140 -0
- package/python/bench/concurrency.py +103 -0
- package/python/bench/e2e_real_models.py +94 -0
- package/python/bench/llm_retry_test.py +241 -0
- package/python/bench/load_test.py +193 -0
- package/python/bench/vector_ivf_upgrade.py +128 -0
- package/python/docs/CHANNELS.md +195 -0
- package/python/docs/GOVERNANCE.md +164 -0
- package/python/docs/RELEASE.md +110 -0
- package/python/docs/RUN.md +75 -0
- package/python/docs/RUN_CN.md +121 -0
- package/python/docs//351/205/215/347/275/256/346/214/207/345/215/227.md +152 -0
- package/python/evals/__init__.py +0 -0
- package/python/evals/governance/README.md +61 -0
- package/python/evals/governance/__init__.py +0 -0
- package/python/evals/governance/cases.py +115 -0
- package/python/evals/governance/compare_embeddings.py +94 -0
- package/python/evals/governance/convergence.svg +11 -0
- package/python/evals/governance/report.json +371 -0
- package/python/evals/governance/run_evals.py +368 -0
- package/python/examples/governance_middleware_demo.py +72 -0
- package/python/examples/langgraph_governance_demo.py +104 -0
- package/python/examples/sample_itinerary.csv +6 -0
- package/python/examples/sample_knowledge.csv +9 -0
- package/python/examples/sample_transactions.csv +14 -0
- package/python/foxclaw/__init__.py +408 -0
- package/python/foxclaw/agents/__init__.py +12 -0
- package/python/foxclaw/agents/agents.py +35 -0
- package/python/foxclaw/agents/base.py +794 -0
- package/python/foxclaw/agents/impl/__init__.py +1 -0
- package/python/foxclaw/agents/impl/_helpers.py +70 -0
- package/python/foxclaw/agents/impl/finance.py +231 -0
- package/python/foxclaw/agents/impl/office.py +350 -0
- package/python/foxclaw/agents/impl/supervisor.py +592 -0
- package/python/foxclaw/agents/mixins/_context.py +128 -0
- package/python/foxclaw/agents/mixins/augment.py +143 -0
- package/python/foxclaw/agents/mixins/llm.py +67 -0
- package/python/foxclaw/agents/mixins/memory.py +41 -0
- package/python/foxclaw/agents/mixins/preference.py +131 -0
- package/python/foxclaw/agents/mixins/prompt.py +71 -0
- package/python/foxclaw/agents/mixins/skillbox.py +58 -0
- package/python/foxclaw/agents/mixins/tool_exec.py +417 -0
- package/python/foxclaw/api/__init__.py +224 -0
- package/python/foxclaw/api/_state.py +43 -0
- package/python/foxclaw/api/bootstrap.py +96 -0
- package/python/foxclaw/api/middleware.py +294 -0
- package/python/foxclaw/api/routes/ahs.py +404 -0
- package/python/foxclaw/api/routes/attachments.py +116 -0
- package/python/foxclaw/api/routes/browser.py +35 -0
- package/python/foxclaw/api/routes/domain.py +306 -0
- package/python/foxclaw/api/routes/knowledge.py +145 -0
- package/python/foxclaw/api/routes/llm_admin.py +449 -0
- package/python/foxclaw/api/routes/memory.py +105 -0
- package/python/foxclaw/api/routes/orchestration.py +39 -0
- package/python/foxclaw/api/routes/recovery.py +44 -0
- package/python/foxclaw/api/routes/review.py +266 -0
- package/python/foxclaw/api/routes/search.py +33 -0
- package/python/foxclaw/api/routes/system.py +311 -0
- package/python/foxclaw/api/routes/task.py +263 -0
- package/python/foxclaw/api/routes/ws.py +64 -0
- package/python/foxclaw/api/spine.py +52 -0
- package/python/foxclaw/browser/__init__.py +13 -0
- package/python/foxclaw/browser/action/__init__.py +1 -0
- package/python/foxclaw/browser/action/action_executor.py +50 -0
- package/python/foxclaw/browser/action/action_types.py +44 -0
- package/python/foxclaw/browser/action/action_verifier.py +68 -0
- package/python/foxclaw/browser/action/url_policy.py +143 -0
- package/python/foxclaw/browser/adapter/__init__.py +1 -0
- package/python/foxclaw/browser/adapter/base_adapter.py +23 -0
- package/python/foxclaw/browser/adapter/web_adapter.py +46 -0
- package/python/foxclaw/browser/driver/__init__.py +1 -0
- package/python/foxclaw/browser/driver/base_driver.py +61 -0
- package/python/foxclaw/browser/driver/playwright_driver.py +170 -0
- package/python/foxclaw/browser/perception/__init__.py +1 -0
- package/python/foxclaw/browser/perception/dom_extractor.py +42 -0
- package/python/foxclaw/browser/perception/element_indexer.py +56 -0
- package/python/foxclaw/browser/perception/semantic_reducer.py +33 -0
- package/python/foxclaw/browser/perception/snapshot.py +29 -0
- package/python/foxclaw/browser/service.py +144 -0
- package/python/foxclaw/browser/session/__init__.py +1 -0
- package/python/foxclaw/browser/session/session_manager.py +57 -0
- package/python/foxclaw/capability/__init__.py +12 -0
- package/python/foxclaw/capability/embedding_service.py +65 -0
- package/python/foxclaw/channels/__init__.py +138 -0
- package/python/foxclaw/channels/discord.py +175 -0
- package/python/foxclaw/channels/dispatcher.py +179 -0
- package/python/foxclaw/channels/feishu.py +215 -0
- package/python/foxclaw/channels/openclaw_bridge.py +151 -0
- package/python/foxclaw/channels/signing.py +187 -0
- package/python/foxclaw/channels/telegram.py +120 -0
- package/python/foxclaw/channels/weixin.py +215 -0
- package/python/foxclaw/cli.py +183 -0
- package/python/foxclaw/cognitive/__init__.py +4 -0
- package/python/foxclaw/cognitive/reasoner.py +81 -0
- package/python/foxclaw/cognitive/state.py +141 -0
- package/python/foxclaw/core/__init__.py +9 -0
- package/python/foxclaw/core/audit_chain.py +131 -0
- package/python/foxclaw/core/audit_sink.py +100 -0
- package/python/foxclaw/core/compaction.py +265 -0
- package/python/foxclaw/core/config.py +65 -0
- package/python/foxclaw/core/confirm_nonce.py +151 -0
- package/python/foxclaw/core/dispatch.py +27 -0
- package/python/foxclaw/core/envfile.py +48 -0
- package/python/foxclaw/core/failure_policy.py +142 -0
- package/python/foxclaw/core/gateway.py +81 -0
- package/python/foxclaw/core/governance_audit.py +171 -0
- package/python/foxclaw/core/idempotency.py +282 -0
- package/python/foxclaw/core/injection_guard.py +202 -0
- package/python/foxclaw/core/memory_adapter.py +489 -0
- package/python/foxclaw/core/metrics.py +88 -0
- package/python/foxclaw/core/model_router.py +985 -0
- package/python/foxclaw/core/paths.py +103 -0
- package/python/foxclaw/core/recovery.py +349 -0
- package/python/foxclaw/core/scheduler.py +141 -0
- package/python/foxclaw/core/secrets.py +131 -0
- package/python/foxclaw/core/sessions.py +155 -0
- package/python/foxclaw/core/settings.py +414 -0
- package/python/foxclaw/core/shared_write.py +186 -0
- package/python/foxclaw/core/steering_queue.py +154 -0
- package/python/foxclaw/core/system_bus.py +84 -0
- package/python/foxclaw/core/thought_chain.py +316 -0
- package/python/foxclaw/core/token_meter.py +231 -0
- package/python/foxclaw/core/tools.py +164 -0
- package/python/foxclaw/core/tracing.py +375 -0
- package/python/foxclaw/core/truth_pipeline.py +110 -0
- package/python/foxclaw/core/update_check.py +149 -0
- package/python/foxclaw/core/vec_recall_adapter.py +477 -0
- package/python/foxclaw/core/verify.py +173 -0
- package/python/foxclaw/core/web_search.py +218 -0
- package/python/foxclaw/finance/__init__.py +15 -0
- package/python/foxclaw/finance/evidence.py +149 -0
- package/python/foxclaw/finance/fx.py +98 -0
- package/python/foxclaw/finance/graph.py +179 -0
- package/python/foxclaw/finance/models.py +146 -0
- package/python/foxclaw/finance/nlparse.py +515 -0
- package/python/foxclaw/finance/policy.py +301 -0
- package/python/foxclaw/finance/reasoner.py +121 -0
- package/python/foxclaw/finance/reasoning.py +319 -0
- package/python/foxclaw/finance/reconcile.py +175 -0
- package/python/foxclaw/finance/runtime.py +500 -0
- package/python/foxclaw/governance/__init__.py +24 -0
- package/python/foxclaw/governance/middleware.py +176 -0
- package/python/foxclaw/harness/__init__.py +17 -0
- package/python/foxclaw/harness/_base.py +66 -0
- package/python/foxclaw/harness/_policy.py +340 -0
- package/python/foxclaw/harness/drift.py +77 -0
- package/python/foxclaw/harness/event_bus.py +28 -0
- package/python/foxclaw/harness/harness.py +358 -0
- package/python/foxclaw/harness/loop_detection.py +145 -0
- package/python/foxclaw/itinerary/__init__.py +10 -0
- package/python/foxclaw/itinerary/amap_client.py +114 -0
- package/python/foxclaw/itinerary/models.py +80 -0
- package/python/foxclaw/itinerary/reasoner.py +96 -0
- package/python/foxclaw/itinerary/reasoning.py +168 -0
- package/python/foxclaw/itinerary/runtime.py +144 -0
- package/python/foxclaw/kernel/__init__.py +13 -0
- package/python/foxclaw/kernel/capabilities.py +72 -0
- package/python/foxclaw/kernel/policy_gate.py +108 -0
- package/python/foxclaw/kernel/process_manager.py +186 -0
- package/python/foxclaw/kernel/scheduler.py +125 -0
- package/python/foxclaw/kernel/sentinel.py +443 -0
- package/python/foxclaw/kernel/sentinel_client.py +243 -0
- package/python/foxclaw/kernel/spine.py +97 -0
- package/python/foxclaw/knowledge/__init__.py +360 -0
- package/python/foxclaw/knowledge/truth_crystallizer.py +89 -0
- package/python/foxclaw/learning/__init__.py +12 -0
- package/python/foxclaw/learning/knowledge_graph.py +144 -0
- package/python/foxclaw/learning/models.py +93 -0
- package/python/foxclaw/learning/reasoner.py +67 -0
- package/python/foxclaw/learning/runtime.py +351 -0
- package/python/foxclaw/learning/spaced_repetition.py +91 -0
- package/python/foxclaw/mcp_server.py +188 -0
- package/python/foxclaw/orchestration/__init__.py +167 -0
- package/python/foxclaw/pipeline/__init__.py +23 -0
- package/python/foxclaw/pipeline/cognitive_pipeline.py +429 -0
- package/python/foxclaw/pipeline/stage_meta.py +21 -0
- package/python/foxclaw/pipeline/supervisor_stages.py +201 -0
- package/python/foxclaw/planning/__init__.py +17 -0
- package/python/foxclaw/planning/llm_planner.py +232 -0
- package/python/foxclaw/planning/planner.py +94 -0
- package/python/foxclaw/search/__init__.py +24 -0
- package/python/foxclaw/search/agent_port.py +190 -0
- package/python/foxclaw/search/evidence.py +109 -0
- package/python/foxclaw/search/external_search.py +50 -0
- package/python/foxclaw/search/hkc_read_port.py +60 -0
- package/python/foxclaw/search/internal_search.py +71 -0
- package/python/foxclaw/search/models.py +127 -0
- package/python/foxclaw/search/planner.py +44 -0
- package/python/foxclaw/search/retriever.py +39 -0
- package/python/foxclaw/search/runtime.py +127 -0
- package/python/foxclaw/search/strategy.py +44 -0
- package/python/foxclaw/skills/__init__.py +559 -0
- package/python/foxclaw/skills/archive.py +111 -0
- package/python/foxclaw/skills/fetch.py +226 -0
- package/python/foxclaw/skills/hooks_spec.py +69 -0
- package/python/foxclaw/skills/install_cmd.py +216 -0
- package/python/foxclaw/skills/lifecycle.py +252 -0
- package/python/foxclaw/skills/markdown_skill.py +175 -0
- package/python/foxclaw/skills/markdown_store.py +39 -0
- package/python/foxclaw/skills/mcp_client.py +184 -0
- package/python/foxclaw/skills/mcp_store.py +40 -0
- package/python/foxclaw/skills/permission.py +145 -0
- package/python/foxclaw/skills/pipeline.py +354 -0
- package/python/foxclaw/skills/policy.py +74 -0
- package/python/foxclaw/skills/review.py +72 -0
- package/python/foxclaw/skills/store.py +57 -0
- package/python/frontend/assets/core_bg.jpg +0 -0
- package/python/frontend/deck/auth.js +25 -0
- package/python/frontend/deck/chat_model_picker.js +483 -0
- package/python/frontend/deck/domain.js +276 -0
- package/python/frontend/deck/main.js +1806 -0
- package/python/frontend/deck/markdown.js +44 -0
- package/python/frontend/deck/settings.js +307 -0
- package/python/frontend/deck/state.js +5 -0
- package/python/frontend/deck/util.js +4 -0
- package/python/frontend/deck/visuals.js +190 -0
- package/python/frontend/deck.css +855 -0
- package/python/frontend/deck.html +686 -0
- package/python/frontend/deck_v2.html +341 -0
- package/python/frontend/planet/index.html +266 -0
- package/python/frontend/planet/planet.css +579 -0
- package/python/frontend/planet/planet.js +1436 -0
- package/python/frontend/planet/vendor/three.core.min.js +6 -0
- package/python/frontend/planet/vendor/three.module.min.js +6 -0
- package/python/frontend/v3/assets/index-CQSBdxk4.js +34 -0
- package/python/frontend/v3/assets/index-D5nIsjms.css +1 -0
- package/python/frontend/v3/index.html +15 -0
- package/python/frontend/widget_runtime.js +252 -0
- package/python/frontend/widgets.js +639 -0
- package/python/frontend_src/index.html +14 -0
- package/python/frontend_src/package-lock.json +1376 -0
- package/python/frontend_src/package.json +19 -0
- package/python/frontend_src/src/App.vue +58 -0
- package/python/frontend_src/src/api.js +82 -0
- package/python/frontend_src/src/components/ChatDock.vue +365 -0
- package/python/frontend_src/src/components/ComposerMenu.vue +75 -0
- package/python/frontend_src/src/components/DocViewer.vue +162 -0
- package/python/frontend_src/src/components/Inspector.vue +235 -0
- package/python/frontend_src/src/components/LeftRail.vue +415 -0
- package/python/frontend_src/src/components/MenuPopover.vue +128 -0
- package/python/frontend_src/src/components/MessageStream.vue +389 -0
- package/python/frontend_src/src/components/ModelPicker.vue +350 -0
- package/python/frontend_src/src/components/QuickIngest.vue +112 -0
- package/python/frontend_src/src/components/Stage.vue +272 -0
- package/python/frontend_src/src/components/ToolMenu.vue +141 -0
- package/python/frontend_src/src/components/TopBar.vue +118 -0
- package/python/frontend_src/src/components/panels/ActivityPanel.vue +82 -0
- package/python/frontend_src/src/components/panels/AgentsPanel.vue +83 -0
- package/python/frontend_src/src/components/panels/KnowledgePanel.vue +425 -0
- package/python/frontend_src/src/components/panels/MemoryPanel.vue +117 -0
- package/python/frontend_src/src/components/panels/PanelBox.vue +50 -0
- package/python/frontend_src/src/components/panels/ReviewPanel.vue +292 -0
- package/python/frontend_src/src/components/panels/SettingsPanel.vue +358 -0
- package/python/frontend_src/src/components/panels/TasksPanel.vue +73 -0
- package/python/frontend_src/src/components/panels/ToolsPanel.vue +746 -0
- package/python/frontend_src/src/components/panels/UsagePanel.vue +105 -0
- package/python/frontend_src/src/lib/fmt.js +44 -0
- package/python/frontend_src/src/lib/i18n.js +53 -0
- package/python/frontend_src/src/lib/locales/en.js +173 -0
- package/python/frontend_src/src/lib/locales/zh.js +174 -0
- package/python/frontend_src/src/lib/md.js +190 -0
- package/python/frontend_src/src/main.js +9 -0
- package/python/frontend_src/src/stores/app.js +91 -0
- package/python/frontend_src/src/stores/chat.js +450 -0
- package/python/frontend_src/src/stores/model.js +96 -0
- package/python/frontend_src/src/stores/panels.js +289 -0
- package/python/frontend_src/src/stores/profile.js +31 -0
- package/python/frontend_src/src/stores/system.js +25 -0
- package/python/frontend_src/src/styles/base.css +138 -0
- package/python/frontend_src/src/styles/panel.css +117 -0
- package/python/frontend_src/src/styles/tokens.css +78 -0
- package/python/frontend_src/vite.config.js +39 -0
- package/python/pyproject.toml +268 -0
- package/python/requirements.txt +311 -0
- package/python/skills/README.md +123 -0
- package/python/skills/execution-contract/SKILL.md +30 -0
- package/python/skills/general-assistant/SKILL.md +34 -0
- package/python/skills/planner/SKILL.md +33 -0
- package/python/skills/schedule-itinerary/SKILL.md +35 -0
- package/python/skills/skill-composition/SKILL.md +31 -0
- package/python/skills/skill-guard/SKILL.md +67 -0
- package/python/skills/skill-memory/SKILL.md +50 -0
- package/python/skills/skill-router/SKILL.md +35 -0
- package/python/tests/conftest.py +54 -0
- package/python/tests/run_all.py +200 -0
- package/python/tests/test_agent_lifecycle.py +326 -0
- package/python/tests/test_ahs_p2.py +393 -0
- package/python/tests/test_anthropic_tools.py +192 -0
- package/python/tests/test_api.py +97 -0
- package/python/tests/test_api_auth.py +79 -0
- package/python/tests/test_api_host_guard.py +69 -0
- package/python/tests/test_attachments.py +151 -0
- package/python/tests/test_audit_chain.py +116 -0
- package/python/tests/test_audit_sink.py +130 -0
- package/python/tests/test_browser.py +149 -0
- package/python/tests/test_browser_request_guard.py +180 -0
- package/python/tests/test_capabilities.py +152 -0
- package/python/tests/test_channel_signing.py +185 -0
- package/python/tests/test_channel_trust.py +109 -0
- package/python/tests/test_channels.py +174 -0
- package/python/tests/test_cli.py +46 -0
- package/python/tests/test_compaction_toolpair.py +119 -0
- package/python/tests/test_config_layering.py +61 -0
- package/python/tests/test_confirm_nonce.py +186 -0
- package/python/tests/test_context_compaction_wiring.py +124 -0
- package/python/tests/test_dispatch.py +89 -0
- package/python/tests/test_domain_evals.py +334 -0
- package/python/tests/test_domain_import.py +72 -0
- package/python/tests/test_domain_reasoners.py +134 -0
- package/python/tests/test_e2e.py +161 -0
- package/python/tests/test_emb_cache.py +97 -0
- package/python/tests/test_embedding_singleton.py +87 -0
- package/python/tests/test_envfile.py +83 -0
- package/python/tests/test_evals_smoke.py +90 -0
- package/python/tests/test_event_spine.py +174 -0
- package/python/tests/test_evidence_semantic.py +88 -0
- package/python/tests/test_evidence_sse.py +94 -0
- package/python/tests/test_file_ingest.py +135 -0
- package/python/tests/test_finance.py +144 -0
- package/python/tests/test_finance_ledger.py +245 -0
- package/python/tests/test_finance_persist.py +174 -0
- package/python/tests/test_gateway.py +125 -0
- package/python/tests/test_governance.py +421 -0
- package/python/tests/test_governance_audit.py +324 -0
- package/python/tests/test_governance_middleware.py +137 -0
- package/python/tests/test_hkc.py +268 -0
- package/python/tests/test_hkc_index_build_manager.py +306 -0
- package/python/tests/test_hkc_manifest_reuse.py +294 -0
- package/python/tests/test_hkc_search_event_sync.py +482 -0
- package/python/tests/test_import_path_guard.py +155 -0
- package/python/tests/test_injection_guard.py +193 -0
- package/python/tests/test_integration.py +117 -0
- package/python/tests/test_itinerary.py +100 -0
- package/python/tests/test_kee_semantic.py +84 -0
- package/python/tests/test_kernel.py +212 -0
- package/python/tests/test_learning.py +101 -0
- package/python/tests/test_llm_admin.py +145 -0
- package/python/tests/test_llm_planner.py +344 -0
- package/python/tests/test_markdown_skills.py +62 -0
- package/python/tests/test_markdown_skills_openclaw.py +66 -0
- package/python/tests/test_mcp_connectors.py +97 -0
- package/python/tests/test_mcp_guardian_discovery.py +87 -0
- package/python/tests/test_mcp_no_memory.py +43 -0
- package/python/tests/test_mcp_policy_gate.py +76 -0
- package/python/tests/test_mcp_server.py +92 -0
- package/python/tests/test_memory_recall.py +92 -0
- package/python/tests/test_metrics.py +58 -0
- package/python/tests/test_multi_chain.py +90 -0
- package/python/tests/test_multimodal.py +122 -0
- package/python/tests/test_negotiation.py +136 -0
- package/python/tests/test_orchestration.py +109 -0
- package/python/tests/test_orchestration_decoupled.py +103 -0
- package/python/tests/test_p3_p5_hardening.py +324 -0
- package/python/tests/test_parallel_dispatch.py +207 -0
- package/python/tests/test_pipeline.py +492 -0
- package/python/tests/test_plan_visible.py +86 -0
- package/python/tests/test_planner.py +88 -0
- package/python/tests/test_policy_gate.py +108 -0
- package/python/tests/test_profile.py +67 -0
- package/python/tests/test_readme_claims.py +163 -0
- package/python/tests/test_reasoner.py +170 -0
- package/python/tests/test_release_check.py +252 -0
- package/python/tests/test_resume_checkpoint.py +148 -0
- package/python/tests/test_routing.py +85 -0
- package/python/tests/test_scheduler.py +138 -0
- package/python/tests/test_search.py +194 -0
- package/python/tests/test_secrets.py +153 -0
- package/python/tests/test_semantic.py +69 -0
- package/python/tests/test_sessions.py +90 -0
- package/python/tests/test_settings.py +265 -0
- package/python/tests/test_shadow_learning.py +290 -0
- package/python/tests/test_shared_write.py +200 -0
- package/python/tests/test_skill_taint_gate.py +145 -0
- package/python/tests/test_skills.py +117 -0
- package/python/tests/test_skills_fetch.py +282 -0
- package/python/tests/test_stats_and_events.py +162 -0
- package/python/tests/test_streaming.py +55 -0
- package/python/tests/test_supervisor_pipeline.py +176 -0
- package/python/tests/test_supervisor_triage.py +102 -0
- package/python/tests/test_taint.py +112 -0
- package/python/tests/test_task_stream.py +74 -0
- package/python/tests/test_thinking_sse.py +66 -0
- package/python/tests/test_thinking_stream.py +76 -0
- package/python/tests/test_tool_center.py +113 -0
- package/python/tests/test_tool_parallel.py +113 -0
- package/python/tests/test_tool_params.py +99 -0
- package/python/tests/test_tool_use.py +229 -0
- package/python/tests/test_toplevel_concurrency.py +116 -0
- package/python/tests/test_tracing.py +256 -0
- package/python/tests/test_truth_crystallizer.py +125 -0
- package/python/tests/test_truth_flow.py +88 -0
- package/python/tests/test_update_check.py +95 -0
- package/python/tests/test_url_policy.py +53 -0
- package/python/tests/test_verify_evidence.py +212 -0
- package/python/tests/test_version_sync.py +100 -0
- package/python/tests/test_web_trigger.py +82 -0
- package/python/tools/check_faiss_type.py +30 -0
- package/python/tools/check_log.ps1 +38 -0
- package/python/tools/ivf_status.py +72 -0
- package/python/tools/mypy_baseline.txt +13 -0
- package/python/tools/mypy_ratchet.py +143 -0
- package/python/tools/pack.py +173 -0
- package/python/tools/release_check.py +349 -0
- package/python/tools/restart_foxclaw.ps1 +71 -0
- package/python/tools/shared_write_audit.py +190 -0
- package/python/tools/size_baseline.txt +28 -0
- package/python/tools/size_check.py +102 -0
- package/python/tools/strip_comments.py +228 -0
- package/python/tools/verify_env.bat +2 -0
- package/python/tools/verify_env.py +25 -0
- package/python/vendor/HMR_LICENSE +37 -0
- package/python/vendor/HMR_README.md +65 -0
- package/python/vendor/hkc/LICENSE +37 -0
- package/python/vendor/hkc/hkc_ace/__init__.py +0 -0
- package/python/vendor/hkc/hkc_ace/ace.py +457 -0
- package/python/vendor/hkc/hkc_ace/skill_taxonomy.json +465 -0
- package/python/vendor/hkc/hkc_api/__init__.py +0 -0
- package/python/vendor/hkc/hkc_api/container.py +416 -0
- package/python/vendor/hkc/hkc_api/ingest_jobs.py +103 -0
- package/python/vendor/hkc/hkc_api/main.py +157 -0
- package/python/vendor/hkc/hkc_api/routes/__init__.py +0 -0
- package/python/vendor/hkc/hkc_api/routes/ability.py +151 -0
- package/python/vendor/hkc/hkc_api/routes/config.py +51 -0
- package/python/vendor/hkc/hkc_api/routes/knowledge.py +630 -0
- package/python/vendor/hkc/hkc_api/routes/search.py +88 -0
- package/python/vendor/hkc/hkc_api/schemas.py +153 -0
- package/python/vendor/hkc/hkc_api/synthesis.py +179 -0
- package/python/vendor/hkc/hkc_core/__init__.py +0 -0
- package/python/vendor/hkc/hkc_core/graph/__init__.py +0 -0
- package/python/vendor/hkc/hkc_core/graph/base.py +188 -0
- package/python/vendor/hkc/hkc_core/graph/sqlite_store.py +789 -0
- package/python/vendor/hkc/hkc_core/models/__init__.py +0 -0
- package/python/vendor/hkc/hkc_core/models/enums.py +65 -0
- package/python/vendor/hkc/hkc_core/models/ku.py +307 -0
- package/python/vendor/hkc/hkc_core/utils/__init__.py +0 -0
- package/python/vendor/hkc/hkc_core/utils/id_gen.py +113 -0
- package/python/vendor/hkc/hkc_crystallizer/__init__.py +44 -0
- package/python/vendor/hkc/hkc_crystallizer/adapters.py +94 -0
- package/python/vendor/hkc/hkc_crystallizer/candidate.py +145 -0
- package/python/vendor/hkc/hkc_crystallizer/crystallizer.py +179 -0
- package/python/vendor/hkc/hkc_crystallizer/ingress.py +90 -0
- package/python/vendor/hkc/hkc_kde/__init__.py +0 -0
- package/python/vendor/hkc/hkc_kde/chunker.py +197 -0
- package/python/vendor/hkc/hkc_kde/extractor.py +623 -0
- package/python/vendor/hkc/hkc_kde/kde.py +298 -0
- package/python/vendor/hkc/hkc_kde/loaders/__init__.py +0 -0
- package/python/vendor/hkc/hkc_kde/loaders/ebook_loader.py +153 -0
- package/python/vendor/hkc/hkc_kde/loaders/office_loader.py +194 -0
- package/python/vendor/hkc/hkc_kde/loaders/pdf_loader.py +162 -0
- package/python/vendor/hkc/hkc_kde/loaders/text_loader.py +157 -0
- package/python/vendor/hkc/hkc_kde/loaders/web_loader.py +91 -0
- package/python/vendor/hkc/hkc_kde/models.py +74 -0
- package/python/vendor/hkc/hkc_kde/packager.py +329 -0
- package/python/vendor/hkc/hkc_kde/relation_disc.py +151 -0
- package/python/vendor/hkc/hkc_kee/__init__.py +0 -0
- package/python/vendor/hkc/hkc_kee/dedup.py +227 -0
- package/python/vendor/hkc/hkc_kee/fingerprint.py +106 -0
- package/python/vendor/hkc/hkc_kee/kee.py +541 -0
- package/python/vendor/hkc/hkc_kep/__init__.py +0 -0
- package/python/vendor/hkc/hkc_kep/event_bus.py +205 -0
- package/python/vendor/hkc/hkc_sdk/__init__.py +63 -0
- package/python/vendor/hkc/hkc_sdk/base.py +151 -0
- package/python/vendor/hkc/hkc_sdk/direct_client.py +153 -0
- package/python/vendor/hkc/hkc_sdk/exceptions.py +39 -0
- package/python/vendor/hkc/hkc_sdk/http_client.py +166 -0
- package/python/vendor/hkc/hkc_sdk/models.py +171 -0
- package/python/vendor/hkc/hkc_search/__init__.py +0 -0
- package/python/vendor/hkc/hkc_search/bm25.py +325 -0
- package/python/vendor/hkc/hkc_search/embedding_backends.py +374 -0
- package/python/vendor/hkc/hkc_search/graph_search.py +132 -0
- package/python/vendor/hkc/hkc_search/hybrid.py +331 -0
- package/python/vendor/hkc/hkc_search/index_build_manager.py +378 -0
- package/python/vendor/hkc/hkc_search/vector_search.py +484 -0
- package/python/vendor/hmr/__init__.py +0 -0
- package/python/vendor/hmr/core/__init__.py +0 -0
- package/python/vendor/hmr/core/hmr.py +684 -0
- package/python/vendor/hmr/core/models.py +310 -0
- package/python/vendor/hmr/engines/__init__.py +0 -0
- package/python/vendor/hmr/engines/evolution.py +710 -0
- package/python/vendor/hmr/engines/jit_compiler.py +472 -0
- package/python/vendor/hmr/engines/lifecycle.py +264 -0
- package/python/vendor/hmr/engines/policy.py +625 -0
- package/python/vendor/hmr/engines/recall.py +260 -0
- package/python/vendor/hmr/engines/runtime_state.py +158 -0
- package/python/vendor/hmr/engines/scheduler.py +323 -0
- package/python/vendor/hmr/engines/semantic.py +150 -0
- package/python/vendor/hmr/engines/temporal.py +261 -0
- package/python/vendor/hmr/engines/thought_chain.py +635 -0
- package/python/vendor/hmr/graph/__init__.py +0 -0
- package/python/vendor/hmr/graph/cwg.py +338 -0
- package/python/vendor/hmr/graph/memory_graph.py +530 -0
- package/python/vendor/hmr/storage/__init__.py +0 -0
- package/python/vendor/hmr/storage/memory_fs.py +300 -0
- package/python/vendor/hmr/storage/vector_store.py +520 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.topbar[data-v-c3cf2a1d]{display:flex;align-items:center;gap:10px;padding:0 16px;background:#ffffff80;-webkit-backdrop-filter:blur(18px) saturate(160%);backdrop-filter:blur(18px) saturate(160%);border-bottom:1px solid var(--line-soft)}.brand[data-v-c3cf2a1d]{display:flex;align-items:center;gap:9px}.logo[data-v-c3cf2a1d]{width:28px;height:28px;border-radius:9px;display:grid;place-items:center;background:var(--green);color:#fff;font-weight:800;font-size:15px;box-shadow:0 4px 12px #1a9d5f52}.brand h1[data-v-c3cf2a1d]{font-size:15px;font-weight:700;letter-spacing:-.01em}.ver[data-v-c3cf2a1d]{font-size:11px;font-weight:600;color:var(--dim);padding:2px 7px;border-radius:var(--r-pill);background:#ffffffb3;border:1px solid var(--line)}.upd[data-v-c3cf2a1d]{display:grid;place-items:center;width:18px;height:18px;margin-left:-3px;border-radius:50%;font-size:11px;font-weight:700;line-height:1;color:var(--amber);background:#d69e2e1f;border:1px solid rgba(214,158,46,.35)}.upd[data-v-c3cf2a1d]:hover{background:#d69e2e33}.spacer[data-v-c3cf2a1d]{flex:1}.stat[data-v-c3cf2a1d]{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--dim)}.stat .val[data-v-c3cf2a1d]{font-weight:700;color:var(--ink)}.stat .val.ok[data-v-c3cf2a1d]{color:var(--green)}.stat .val.bad[data-v-c3cf2a1d]{color:var(--amber)}.stat .val.dim[data-v-c3cf2a1d]{color:var(--dim)}.tbtn[data-v-c3cf2a1d]{font-size:12.5px;font-weight:600;color:var(--ink);padding:6px 11px;border-radius:var(--r-sm);border:1px solid var(--line);background:#ffffffb3;transition:color .15s,background .15s}.tbtn[data-v-c3cf2a1d]:hover{color:var(--ink);background:#fff}.tbtn.on[data-v-c3cf2a1d]{color:var(--green);background:#fff;border-color:#1a9d5f52}.nav-pop[data-v-28d78e1a]{position:fixed;z-index:var(--z-menu);width:214px;max-height:min(64vh,420px);display:flex;flex-direction:column;border-radius:var(--r-mid);background:#ffffffe0;-webkit-backdrop-filter:blur(24px) saturate(180%);backdrop-filter:blur(24px) saturate(180%);border:1px solid rgba(255,255,255,.9);box-shadow:var(--sh-pop);overflow:hidden;animation:pop-in-28d78e1a .16s ease}@keyframes pop-in-28d78e1a{0%{opacity:0;transform:translateY(-6px) scale(.985)}}.pop-head[data-v-28d78e1a]{display:flex;align-items:center;justify-content:space-between;padding:9px 11px;flex-shrink:0;font-size:11px;font-weight:700;letter-spacing:.06em;color:var(--faint);text-transform:uppercase;border-bottom:1px solid var(--line-soft)}.pop-head .x[data-v-28d78e1a]{cursor:pointer;font-size:11px;color:var(--faint);padding:2px 4px}.pop-head .x[data-v-28d78e1a]:hover{color:var(--ink)}.pop-body[data-v-28d78e1a]{padding:6px;overflow-y:auto}.pop-sec[data-v-28d78e1a]{padding:9px 6px 5px;font-size:11px;font-weight:700;letter-spacing:.08em;color:var(--dim);text-transform:uppercase}.pop-item[data-v-28d78e1a]{width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 9px;border-radius:var(--r-sm);transition:background .14s}.pop-item .lbl[data-v-28d78e1a]{font-size:13px;font-weight:600;color:var(--ink)}.pop-item .tag[data-v-28d78e1a]{font-size:11px;font-weight:600;color:var(--dim)}.pop-item[data-v-28d78e1a]:hover{background:var(--surface-2)}.pop-item.on[data-v-28d78e1a]{background:var(--accent-soft)}.pop-item.on .lbl[data-v-28d78e1a]{color:var(--accent);font-weight:600}.rail-left[data-v-310e54b3]{padding:12px;gap:10px}.new-sess[data-v-310e54b3]{display:flex;align-items:center;justify-content:center;gap:6px;padding:9px 12px;flex-shrink:0;font-size:13px;font-weight:600;color:var(--green);background:#1a9d5f1a;border-radius:var(--r-sm);transition:background .16s,transform .1s}.new-sess[data-v-310e54b3]:hover{background:#1a9d5f2b}.new-sess[data-v-310e54b3]:active{transform:scale(.985)}.rail-nav[data-v-310e54b3]{display:flex;flex-direction:column;gap:2px;flex-shrink:0}.rail-row[data-v-310e54b3]{position:relative;display:flex;align-items:center}.rail-item[data-v-310e54b3]{flex:1;min-width:0;display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:var(--r-sm);border:1px solid transparent;transition:background .14s,border-color .14s}.rail-item .ic[data-v-310e54b3]{width:15px;height:15px;display:grid;place-items:center;color:var(--dim);flex-shrink:0}.rail-item .ic svg[data-v-310e54b3]{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.rail-item b[data-v-310e54b3]{flex:1;min-width:0;text-align:left;font-size:13px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rail-row:hover .rail-item[data-v-310e54b3]{background:#fff9}.rail-row.on .rail-item[data-v-310e54b3]{background:#ffffffeb;border-color:var(--line);box-shadow:0 1px 2px #17201a0d}.rail-row.on .rail-item .ic[data-v-310e54b3]{color:var(--green)}.rail-row.on .rail-item b[data-v-310e54b3]{font-weight:600}.rail-row.sub .rail-item[data-v-310e54b3]{background:#ffffff80}.rail-row.sub .rail-item .ic[data-v-310e54b3]{color:var(--green)}.beta[data-v-310e54b3]{flex-shrink:0;font-size:10px;font-weight:700;letter-spacing:.08em;color:var(--amber);padding:2px 5px;border-radius:4px;background:#c774001f}.rail-acts[data-v-310e54b3]{position:absolute;right:5px;top:50%;transform:translateY(-50%);display:flex;gap:2px;padding-left:14px;background:linear-gradient(90deg,#fff0,#fffffff0 34%);opacity:0;transition:opacity .13s;pointer-events:none}.rail-row:hover .rail-acts[data-v-310e54b3],.rail-acts[data-v-310e54b3]:focus-within{opacity:1;pointer-events:auto}.act[data-v-310e54b3]{width:21px;height:21px;display:grid;place-items:center;border-radius:6px;color:var(--dim);transition:background .13s,color .13s}.act svg[data-v-310e54b3]{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.act[data-v-310e54b3]:hover{background:#1a9d5f1f;color:var(--green)}.cur[data-v-310e54b3]{font-size:11.5px;color:var(--dim);flex-shrink:0}.caret[data-v-310e54b3]{font-size:10.5px;color:var(--dim);transition:transform .18s;flex-shrink:0}.caret.open[data-v-310e54b3]{transform:rotate(180deg)}.sec-head[data-v-310e54b3]{display:flex;align-items:center;justify-content:space-between;padding:2px 4px 0;font-size:11px;font-weight:700;letter-spacing:.06em;color:var(--dim);text-transform:uppercase;flex-shrink:0}.sec-head em[data-v-310e54b3]{font-size:11px;font-weight:700;color:var(--ink);padding:2px 7px;border-radius:var(--r-pill);background:#ffffffdb;border:1px solid var(--line)}.ns-list[data-v-310e54b3]{display:flex;flex-direction:column;gap:3px;flex:1;margin:0 -4px;padding:0 4px}.rail-foot[data-v-310e54b3]{flex-shrink:0;margin-top:2px;padding-top:8px;border-top:1px solid var(--line)}.ns-row[data-v-310e54b3]{position:relative;display:flex;align-items:center;border-radius:var(--r-sm);border:1px solid transparent;transition:background .14s,border-color .14s}.ns-row[data-v-310e54b3]:hover{background:#ffffffa8}.ns-row.on[data-v-310e54b3]{background:#ffffffeb;border-color:var(--line);box-shadow:0 1px 2px #17201a0d}.ns-item[data-v-310e54b3]{flex:1;min-width:0;text-align:left;display:flex;flex-direction:column;gap:2px;padding:8px 10px}.ns-item b[data-v-310e54b3]{font-size:13px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ns-item span[data-v-310e54b3]{font-size:11.5px;color:var(--dim)}.ns-acts[data-v-310e54b3]{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:flex;gap:2px;padding-left:16px;background:linear-gradient(90deg,#fff0,#fffffff5 36%);opacity:0;pointer-events:none;transition:opacity .13s}.ns-row:hover .ns-acts[data-v-310e54b3],.ns-acts[data-v-310e54b3]:focus-within{opacity:1;pointer-events:auto}.act.del[data-v-310e54b3]:hover{background:#b4443a1f;color:#b4443a}.ns-edit[data-v-310e54b3]{width:100%;padding:7px 9px;font-size:12.5px;color:var(--ink);background:#fff;border:1px solid var(--green);border-radius:var(--r-sm);outline:none}.cli[data-v-045bb22d]{flex:1;min-width:0;display:flex;flex-direction:column;margin:8px;border-radius:var(--r-mid);overflow:hidden;background:var(--cli-bg);border:1px solid rgba(255,255,255,.06);box-shadow:0 18px 44px #0b0f0a57}.term-bar[data-v-045bb22d]{display:flex;align-items:center;gap:6px;flex-shrink:0;padding:9px 12px;background:var(--cli-bg-2);border-bottom:1px solid var(--cli-line)}.tl[data-v-045bb22d]{width:9px;height:9px;border-radius:50%;background:#ffffff24}.tl[data-v-045bb22d]:first-child{background:#ff685c9e}.tl[data-v-045bb22d]:nth-child(2){background:#e2c07a9e}.tl[data-v-045bb22d]:nth-child(3){background:#7fe08c94}.term-bar .path[data-v-045bb22d]{margin-left:8px;font-family:var(--mono);font-size:11.5px;color:var(--cli-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.term-bar .lang[data-v-045bb22d]{margin-left:auto;flex-shrink:0;font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.06em;color:var(--cli-bg);background:var(--cli-acc);padding:2px 8px;border-radius:var(--r-pill)}.term-body[data-v-045bb22d]{flex:1;overflow:auto;padding:10px 0 16px;font-family:var(--mono);font-size:12.5px;line-height:1.72}.term-body[data-v-045bb22d]::-webkit-scrollbar-thumb{background:#ffffff29}.row[data-v-045bb22d]{display:flex;white-space:pre}.row[data-v-045bb22d]:hover{background:#ffffff09}.no[data-v-045bb22d]{flex-shrink:0;width:48px;text-align:right;padding-right:14px;color:#ffffff6b;user-select:none}.code[data-v-045bb22d]{color:var(--cli-ink);padding-right:24px}.read[data-v-045bb22d]{flex:1;overflow-y:auto;padding:34px 8px 60px}.read-head[data-v-045bb22d],.read-body[data-v-045bb22d]{max-width:68ch;margin:0 auto}.read-head[data-v-045bb22d]{padding:0 20px 18px;border-bottom:1px solid var(--line-soft)}.read-head h2[data-v-045bb22d]{font-family:var(--serif);font-size:23px;font-weight:600;letter-spacing:-.01em;line-height:1.4}.read-meta[data-v-045bb22d]{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:8px;font-size:11.5px;color:var(--dim)}.read-meta code[data-v-045bb22d]{font-family:var(--mono);font-size:11.5px;color:var(--ink)}.read-body[data-v-045bb22d]{padding:20px 20px 0}.read-body[data-v-045bb22d] p{font-family:var(--serif);font-size:15px;line-height:1.92;color:#24302a;margin-bottom:15px;text-align:justify}.read-body[data-v-045bb22d] h3,.read-body[data-v-045bb22d] h4,.read-body[data-v-045bb22d] h5{font-family:var(--serif);color:var(--ink);line-height:1.5;margin:22px 0 8px}.read-body[data-v-045bb22d] h3{font-size:18px;font-weight:650}.read-body[data-v-045bb22d] h4{font-size:15.5px;font-weight:600}.read-body[data-v-045bb22d] h5{font-size:12px;font-weight:700;letter-spacing:.06em;color:var(--dim);text-transform:uppercase}.read-body[data-v-045bb22d] ul{margin:0 0 15px;padding-left:18px}.read-body[data-v-045bb22d] li{font-family:var(--serif);font-size:14.5px;line-height:1.85;color:#24302a;margin-bottom:5px}.read-body[data-v-045bb22d] li::marker{color:var(--faint)}.read-body[data-v-045bb22d] blockquote{margin:0 0 15px;padding:8px 14px;border-left:2px solid var(--line);font-family:var(--serif);font-size:14px;line-height:1.85;color:var(--dim)}.read-body[data-v-045bb22d] hr{margin:20px 0;border:0;border-top:1px solid var(--line-soft)}.read-body[data-v-045bb22d] strong{font-weight:650;color:#16201b}.read-body[data-v-045bb22d] code{font-family:var(--mono);font-size:12px;padding:1px 5px;border-radius:4px;background:#1a9d5f17;color:var(--green)}.read-body[data-v-045bb22d] a{color:var(--green);border-bottom:1px solid rgba(26,157,95,.3)}.read-body[data-v-045bb22d] ol{margin:0 0 15px;padding-left:20px}.read-body[data-v-045bb22d] h2{font-family:var(--serif);font-size:20px;font-weight:650;line-height:1.5;color:var(--ink);margin:26px 0 10px}.read-body[data-v-045bb22d] pre{margin:0 0 15px;padding:11px 13px;background:var(--cli-bg);border-radius:var(--r-sm);overflow-x:auto}.read-body[data-v-045bb22d] pre code{padding:0;background:none;color:var(--cli-ink);font-size:12px;line-height:1.72}.read-body[data-v-045bb22d] table{width:100%;border-collapse:collapse;margin:0 0 15px}.read-body[data-v-045bb22d] th,.read-body[data-v-045bb22d] td{padding:6px 10px;border-bottom:1px solid var(--line-soft);font-size:13px;text-align:left;vertical-align:top}.read-body[data-v-045bb22d] th{font-size:11.5px;font-weight:600;color:var(--dim)}.ms[data-v-efc12ae7]{flex:1;min-height:0;overflow-y:auto}.ms-in[data-v-efc12ae7]{max-width:780px;margin:0 auto;padding:18px 22px 26px;display:flex;flex-direction:column;gap:20px}.msg.user[data-v-efc12ae7]{display:flex;justify-content:flex-end}.u-body[data-v-efc12ae7]{max-width:78%;display:flex;flex-direction:column;align-items:flex-end;gap:5px}.u-atts[data-v-efc12ae7]{display:flex;gap:5px;flex-wrap:wrap;justify-content:flex-end}.u-att[data-v-efc12ae7]{font-size:11.5px;padding:3px 9px;border-radius:var(--r-pill);color:var(--ink);background:#ffffffe6;border:1px solid var(--line)}.u-text[data-v-efc12ae7]{padding:9px 14px;border-radius:14px 14px 4px;font-size:13.5px;line-height:1.65;color:var(--ink);background:linear-gradient(180deg,#fff,#f2f8ee);border:1px solid var(--line-soft);box-shadow:0 1px 2px #17201a0d;white-space:pre-wrap;word-break:break-word}.u-time[data-v-efc12ae7]{font-size:11px;color:var(--faint);font-family:var(--mono)}.a-body[data-v-efc12ae7]{display:flex;flex-direction:column;gap:9px}.a-head[data-v-efc12ae7]{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--dim)}.avatar[data-v-efc12ae7]{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 6px #1a9d5f80}.avatar.live[data-v-efc12ae7]{animation:pulse-efc12ae7 1.1s ease-in-out infinite}@keyframes pulse-efc12ae7{50%{opacity:.35;transform:scale(.8)}}.who[data-v-efc12ae7]{font-weight:700;color:var(--ink)}.a-head .stage[data-v-efc12ae7]{padding:2px 8px;border-radius:var(--r-pill);background:#1a9d5f1f;color:var(--green);font-family:var(--mono);font-size:10.5px;font-weight:600}.a-head .live-tag[data-v-efc12ae7]{color:var(--green);font-size:10.5px;font-weight:600}.a-time[data-v-efc12ae7]{margin-left:auto;font-family:var(--mono)}.a-text[data-v-efc12ae7]{font-size:13.5px;line-height:1.8;color:var(--ink);word-break:break-word;white-space:pre-wrap}.a-text[data-v-efc12ae7] pre,.a-text[data-v-efc12ae7] pre code{white-space:pre}.a-text.waiting[data-v-efc12ae7]{color:var(--faint)}.a-text[data-v-efc12ae7] p{margin:0 0 8px}.a-text[data-v-efc12ae7] p:last-child{margin-bottom:0}.a-text[data-v-efc12ae7] h2,.a-text[data-v-efc12ae7] h3,.a-text[data-v-efc12ae7] h4,.a-text[data-v-efc12ae7] h5{font-family:var(--serif);color:var(--ink);line-height:1.5;margin:14px 0 6px}.a-text[data-v-efc12ae7] h2{font-size:16.5px;font-weight:650}.a-text[data-v-efc12ae7] h3{font-size:15px;font-weight:650}.a-text[data-v-efc12ae7] h4,.a-text[data-v-efc12ae7] h5{font-size:13.5px;font-weight:650}.a-text[data-v-efc12ae7] ul,.a-text[data-v-efc12ae7] ol{margin:0 0 8px;padding-left:20px}.a-text[data-v-efc12ae7] li{margin-bottom:3px}.a-text[data-v-efc12ae7] li::marker{color:var(--faint)}.a-text[data-v-efc12ae7] blockquote{margin:0 0 8px;padding:3px 10px;border-left:2px solid var(--line);color:var(--dim)}.a-text[data-v-efc12ae7] hr{margin:12px 0;border:0;border-top:1px solid var(--line-soft)}.a-text[data-v-efc12ae7] strong{font-weight:650;color:var(--ink)}.a-text[data-v-efc12ae7] del{color:var(--faint)}.a-text[data-v-efc12ae7] code{font-family:var(--mono);font-size:12px;padding:1px 5px;border-radius:4px;background:#1a9d5f17;color:var(--green);white-space:pre-wrap}.a-text[data-v-efc12ae7] pre{margin:8px 0;padding:10px 12px;background:#17211c;border-radius:var(--r-sm);overflow-x:auto}.a-text[data-v-efc12ae7] pre code{padding:0;background:none;color:#dfe9e2;font-size:12px;line-height:1.7;white-space:pre}.a-text[data-v-efc12ae7] table{display:block;overflow-x:auto;border-collapse:collapse;margin:8px 0;font-size:12.5px}.a-text[data-v-efc12ae7] th,.a-text[data-v-efc12ae7] td{padding:4px 9px;border-bottom:1px solid var(--line-soft);text-align:left;vertical-align:top}.a-text[data-v-efc12ae7] th{color:var(--dim);font-size:11.5px}.a-text[data-v-efc12ae7] a{color:var(--green);border-bottom:1px solid rgba(26,157,95,.3)}.a-text.streaming[data-v-efc12ae7]>:last-child:after{content:"";display:inline-block;width:6px;height:13px;margin-left:3px;vertical-align:-2px;background:var(--green);animation:blink-efc12ae7 1s step-end infinite}@keyframes blink-efc12ae7{50%{opacity:0}}.dots[data-v-efc12ae7]{animation:blink-efc12ae7 1.2s step-end infinite;letter-spacing:2px}.fold[data-v-efc12ae7]{border-radius:var(--r-sm);background:#f1f4efb3;border:1px solid var(--line-soft);overflow:hidden}.fold summary[data-v-efc12ae7]{display:flex;align-items:center;gap:7px;padding:7px 11px;cursor:pointer;font-size:12px;font-weight:600;color:var(--ink);list-style:none}.fold summary[data-v-efc12ae7]::-webkit-details-marker{display:none}.fold summary[data-v-efc12ae7]:before{content:"▸";font-size:10px;color:var(--dim)}.fold[open] summary[data-v-efc12ae7]:before{content:"▾"}.fold summary em[data-v-efc12ae7]{font-style:normal;font-family:var(--mono);font-size:10.5px;color:var(--dim)}.fold-body[data-v-efc12ae7]{margin:0;padding:2px 12px 10px;font-size:11.5px;line-height:1.7;color:var(--dim);white-space:pre-wrap;word-break:break-word;max-height:280px;overflow-y:auto}.fold-body ol[data-v-efc12ae7]{margin:0;padding-left:18px}.fold.think .fold-body[data-v-efc12ae7]{font-family:var(--mono);font-size:11px}.fold.ev .fold-body[data-v-efc12ae7]{padding-bottom:8px}.ev-row[data-v-efc12ae7]{display:flex;align-items:baseline;gap:7px;padding:3px 0;flex-wrap:wrap}.ev-row b[data-v-efc12ae7]{font-size:12px;font-weight:700;color:var(--ink)}.ev-st[data-v-efc12ae7]{font-family:var(--mono);font-size:10.5px;color:var(--dim)}.ev-dot[data-v-efc12ae7]{width:5px;height:5px;border-radius:50%;background:var(--amber);flex-shrink:0}.ev-dot.verified[data-v-efc12ae7]{background:var(--green)}.ev-dot.failed[data-v-efc12ae7]{background:var(--red)}.ev-link[data-v-efc12ae7],.ev-file[data-v-efc12ae7]{font-size:11.5px;color:var(--accent);text-decoration:none}.ev-file[data-v-efc12ae7]{color:var(--dim)}.ev-link[data-v-efc12ae7]:hover{text-decoration:underline}.sres[data-v-efc12ae7]{border-radius:var(--r-sm);background:#ffffffbf;border:1px solid var(--line-soft);overflow:hidden}.sres-h[data-v-efc12ae7]{display:flex;align-items:center;gap:10px;padding:7px 11px;border-bottom:1px solid var(--line-soft);font-size:10.5px;color:var(--dim);font-family:var(--mono)}.sres-h .sroute[data-v-efc12ae7]{padding:2px 7px;border-radius:var(--r-pill);color:var(--green);background:#1a9d5f1f;font-weight:700}.srow[data-v-efc12ae7]{display:flex;align-items:baseline;gap:8px;padding:6px 10px;border-bottom:1px solid rgba(23,32,26,.04)}.srow[data-v-efc12ae7]:last-child{border-bottom:0}.ssrc[data-v-efc12ae7]{flex-shrink:0;font-size:10.5px;font-weight:600;padding:2px 6px;border-radius:4px;color:var(--dim);background:var(--surface-2)}.ssrc.knowledge[data-v-efc12ae7]{color:var(--green);background:#1a9d5f1f}.ssrc.web[data-v-efc12ae7]{color:var(--accent);background:#0a84ff1f}.srow p[data-v-efc12ae7]{flex:1;min-width:0;font-size:12px;line-height:1.6;color:var(--ink);word-break:break-word}.srow em[data-v-efc12ae7]{font-style:normal;font-family:var(--mono);font-size:10.5px;color:var(--dim)}.notice[data-v-efc12ae7]{padding:6px 10px;border-radius:var(--r-sm);font-size:11.5px;color:var(--amber);background:#c88c2817}.a-acts[data-v-efc12ae7]{display:flex;gap:6px;opacity:0;transition:opacity .13s}.msg:hover .a-acts[data-v-efc12ae7],.a-acts[data-v-efc12ae7]:focus-within{opacity:1}.mini[data-v-efc12ae7]{font-size:11.5px;padding:3px 10px;border-radius:var(--r-pill);color:var(--dim);background:#ffffffdb;border:1px solid var(--line);transition:color .13s,border-color .13s,background .13s}.mini[data-v-efc12ae7]:hover{color:var(--green);background:#fff;border-color:#1a9d5f59}@media(hover:none){.a-acts[data-v-efc12ae7]{opacity:1}}.err[data-v-efc12ae7]{padding:7px 10px;border-radius:var(--r-sm);font-size:11.5px;color:var(--red);background:#e5484d12;border:1px solid rgba(229,72,77,.16);white-space:pre-wrap}.panel[data-v-a7fcdff6]{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}.ph[data-v-a7fcdff6]{display:flex;align-items:center;gap:10px;flex-shrink:0;padding:11px 16px 10px;border-bottom:1px solid var(--line-soft)}.tt[data-v-a7fcdff6]{display:flex;align-items:baseline;gap:8px;min-width:0}.tt h2[data-v-a7fcdff6]{font-size:13.5px;font-weight:650;letter-spacing:-.01em;color:var(--ink)}.rf[data-v-a7fcdff6]{margin-left:auto;flex-shrink:0;padding:5px 11px;border-radius:var(--r-pill);font-size:11.5px;font-weight:600;color:var(--ink);background:#ffffffdb;border:1px solid var(--line);transition:color .14s,background .14s,border-color .14s}.rf[data-v-a7fcdff6]:hover{color:var(--green);background:#fff;border-color:#1a9d5f59}.rf.spin[data-v-a7fcdff6]{color:var(--dim)}.pb[data-v-a7fcdff6]{flex:1;padding:14px 16px 18px}.pn-row.static[data-v-cdbea439]:hover{background:transparent}.id[data-v-828bb5bf]{font-family:var(--mono);font-size:11px;font-style:normal;color:var(--dim);margin-left:4px}.det[data-v-828bb5bf]{margin:2px 0 8px 10px;padding:8px 12px;border-left:2px solid var(--line)}.kv[data-v-828bb5bf]{display:flex;justify-content:space-between;gap:12px;padding:4px 0;font-size:12px;color:var(--dim)}.kv b[data-v-828bb5bf]{font-weight:600;color:var(--ink);font-family:var(--mono);font-size:11.5px;text-align:right}.sw[data-v-5b252a48]{flex-shrink:0;padding:4px 10px;border-radius:var(--r-pill);font-size:11px;font-family:var(--mono);background:var(--surface-2);color:var(--faint);border:1px solid transparent}.sw.on[data-v-5b252a48]{background:#1a9d5f1f;color:var(--green)}.sw[data-v-5b252a48]:disabled{opacity:.5}.mbtn[data-v-5b252a48]{flex-shrink:0;padding:4px 10px;border-radius:var(--r-pill);font-size:11px;font-family:var(--mono);color:var(--dim);background:#fffc;border:1px solid var(--line-soft);transition:color .13s,border-color .13s,background .13s}.mbtn[data-v-5b252a48]:hover{color:var(--green);border-color:#1a9d5f59;background:#fff}.mbtn.on[data-v-5b252a48]{color:var(--green);background:#1a9d5f1a;border-color:#1a9d5f66}.mbtn.danger[data-v-5b252a48]:hover{color:var(--red);border-color:#e5484d59}.mbtn[data-v-5b252a48]:disabled{opacity:.5}.tk-form[data-v-5b252a48],.tk-test[data-v-5b252a48]{margin:4px 0 6px;padding:11px 12px;border-radius:var(--r-mid);background:#ffffffdb;border:1px solid var(--line-soft)}.tk-test[data-v-5b252a48]{display:flex;flex-direction:column;gap:7px}.tk-test .f span em[data-v-5b252a48]{font-style:normal;font-weight:600;font-family:var(--mono);font-size:11px;color:var(--dim)}.frow[data-v-5b252a48]{display:flex;gap:8px}.frow .f[data-v-5b252a48]{flex:1 1 0;min-width:0}.frow .f.grow[data-v-5b252a48]{flex:2 1 0}.frow .f.narrow[data-v-5b252a48]{flex:0 1 104px}.f[data-v-5b252a48]{display:block;margin-bottom:7px}.f>span[data-v-5b252a48]{display:block;margin-bottom:3px;font-size:11px;color:var(--faint)}.f input[data-v-5b252a48],.f select[data-v-5b252a48],.f textarea[data-v-5b252a48]{display:block;width:100%;padding:5px 8px;border-radius:6px;font-family:inherit;font-size:12.5px;color:var(--ink);background:#17201a0a;border:1px solid transparent;outline:none;transition:border-color .14s,background .14s}.f textarea[data-v-5b252a48]{resize:vertical;line-height:1.6}.f input[data-v-5b252a48]:focus,.f select[data-v-5b252a48]:focus,.f textarea[data-v-5b252a48]:focus{border-color:var(--line);background:#fff}.f input[data-v-5b252a48]::placeholder,.f textarea[data-v-5b252a48]::placeholder{color:var(--dim)}.f input[type=file][data-v-5b252a48]{padding:4px 6px;font-size:11.5px;color:var(--dim)}.chk[data-v-5b252a48]{display:flex;align-items:center;gap:6px;margin-bottom:6px;font-size:12px;color:var(--dim)}.chk input[data-v-5b252a48]{accent-color:var(--green)}.fbar[data-v-5b252a48]{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:3px}.go[data-v-5b252a48]{flex-shrink:0;padding:6px 15px;border-radius:var(--r-pill);font-size:12.5px;font-weight:600;color:#fff;background:var(--green);transition:opacity .15s,transform .12s}.go[data-v-5b252a48]:hover:not(:disabled){opacity:.9}.go[data-v-5b252a48]:active:not(:disabled){transform:scale(.97)}.go[data-v-5b252a48]:disabled{background:#17201a1f;color:var(--faint)}.go.warn[data-v-5b252a48]{background:var(--amber)}.tip[data-v-5b252a48]{flex:1 1 auto;min-width:0;font-size:11.5px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tip.dim[data-v-5b252a48]{color:var(--faint)}.tip.ok[data-v-5b252a48]{color:var(--green)}.tip.bad[data-v-5b252a48]{color:var(--red);white-space:normal}.tk-res[data-v-5b252a48]{margin-top:4px;padding:8px 10px;border-radius:var(--r-sm);background:#17201a08;border:1px solid var(--line-soft)}.tk-res .r-h[data-v-5b252a48]{display:flex;gap:6px;font-size:12px;color:var(--dim)}.tk-res .r-h b[data-v-5b252a48]{font-family:var(--mono);font-size:11.5px;color:var(--ink)}.tk-res.bad .r-h b[data-v-5b252a48]{color:var(--amber)}.tk-res pre[data-v-5b252a48]{margin:6px 0 0;max-height:220px;overflow:auto;font-family:var(--mono);font-size:11.5px;line-height:1.6;color:var(--dim);white-space:pre-wrap;word-break:break-word}.pn-note.meta[data-v-5b252a48]{margin-top:6px}.pn-note.meta.bad[data-v-5b252a48]{color:var(--red)}.acts[data-v-1a916225]{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.btn[data-v-1a916225]{padding:7px 13px;border-radius:var(--r-sm);font-size:11.5px;color:var(--green);font-weight:600;background:#1a9d5f1a;border:1px solid rgba(26,157,95,.16)}.btn[data-v-1a916225]:hover{background:#1a9d5f29}.hint[data-v-1a916225]{font-size:11.5px;color:var(--dim)}.kb-in[data-v-11ecf8c3]{margin-bottom:14px;border-radius:var(--r-mid);background:#ffffffe6;border:1px solid rgba(26,157,95,.16);overflow:hidden;transition:border-color .15s,box-shadow .15s}.kb-in[data-v-11ecf8c3]:focus-within{border-color:#1a9d5f61;box-shadow:0 2px 12px #1a9d5f14}.kb-in textarea[data-v-11ecf8c3]{display:block;width:100%;padding:11px 12px 6px;font-family:var(--sans);font-size:13px;line-height:1.7;color:var(--ink);background:transparent;border:0;outline:none;resize:vertical;min-height:62px}.kb-in textarea[data-v-11ecf8c3]::placeholder{color:var(--dim)}.kb-bar[data-v-11ecf8c3]{display:flex;align-items:center;gap:6px;padding:6px 8px 8px 12px;border-top:1px solid var(--line-soft)}.kb-bar input[data-v-11ecf8c3]{padding:4px 8px;border-radius:6px;font-size:11.5px;color:var(--ink);background:#17201a0a;border:1px solid transparent;outline:none}.kb-bar input[data-v-11ecf8c3]:focus{border-color:var(--line);background:#fff}.kb-bar input[data-v-11ecf8c3]::placeholder{color:var(--dim)}.f-title[data-v-11ecf8c3]{flex:1 1 110px;max-width:190px;min-width:0}.f-domain[data-v-11ecf8c3]{flex:0 1 96px;min-width:60px}.tip[data-v-11ecf8c3]{flex:1 1 auto;min-width:0;font-size:11.5px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tip.dim[data-v-11ecf8c3]{color:var(--faint)}.tip.ok[data-v-11ecf8c3]{color:var(--green)}.tip.bad[data-v-11ecf8c3]{color:var(--red)}.go[data-v-11ecf8c3]{flex-shrink:0;padding:6px 15px;border-radius:var(--r-pill);font-size:11.5px;font-weight:600;color:#fff;background:var(--green);transition:opacity .15s,transform .12s}.go[data-v-11ecf8c3]:hover:not(:disabled){opacity:.9}.go[data-v-11ecf8c3]:active:not(:disabled){transform:scale(.97)}.go[data-v-11ecf8c3]:disabled{background:#17201a12;color:var(--dim);border:1px solid var(--line-soft)}.meta[data-v-11ecf8c3]{margin-top:8px}.sec-gap[data-v-11ecf8c3]{margin-top:14px}.pn-note.meta.bad[data-v-11ecf8c3]{color:var(--red)}.kb-find[data-v-11ecf8c3]{display:flex;align-items:center;gap:6px;margin-bottom:8px}.kb-find input[data-v-11ecf8c3]{flex:1 1 auto;min-width:0;padding:7px 10px;border-radius:var(--r-sm);font-size:12.5px;color:var(--ink);background:#ffffffe6;border:1px solid var(--line-soft);outline:none;transition:border-color .15s}.kb-find input[data-v-11ecf8c3]:focus{border-color:#1a9d5f73}.kb-find input[data-v-11ecf8c3]::placeholder{color:var(--dim)}.kb-find select[data-v-11ecf8c3]{padding:6px 8px;border-radius:var(--r-sm);font-size:12px;font-weight:600;color:var(--ink);background:#ffffffe6;border:1px solid var(--line);outline:none}.kb-find .go[data-v-11ecf8c3]{padding:6px 13px}.kb-hits[data-v-11ecf8c3]{display:flex;flex-direction:column;gap:2px}.kb-hit[data-v-11ecf8c3]{display:flex;align-items:center;gap:8px;width:100%;padding:7px 9px;border-radius:var(--r-sm);text-align:left;transition:background .13s}.kb-hit[data-v-11ecf8c3]:hover{background:#ffffffbf}.kb-hit .m[data-v-11ecf8c3]{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.kb-hit .m b[data-v-11ecf8c3]{font-size:13px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kb-hit .m .s[data-v-11ecf8c3]{font-size:11.5px;color:var(--dim)}.kb-hit .r[data-v-11ecf8c3]{flex-shrink:0;font-size:11.5px;color:var(--dim);font-variant-numeric:tabular-nums}.pn-chips.gap[data-v-11ecf8c3]{margin-top:8px}.kb-ab[data-v-11ecf8c3]{margin-top:10px;padding:10px 12px;border-radius:var(--r-mid);background:#ffffffdb;border:1px solid var(--line-soft)}.kb-ab-h[data-v-11ecf8c3]{display:flex;align-items:baseline;gap:6px;font-size:13px;font-weight:600;color:var(--ink);margin-bottom:5px}.kb-ab-h .v[data-v-11ecf8c3]{font-size:11.5px;font-weight:600;color:var(--dim)}.rv-grid[data-v-1a353dab]{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);gap:22px;align-items:start}@container (max-width: 820px){.rv-grid[data-v-1a353dab]{grid-template-columns:minmax(0,1fr);gap:20px}}.card[data-v-1a353dab]{padding:16px 18px 18px;border-radius:var(--r-md);background:#ffffffdb;border:1px solid var(--line-soft);box-shadow:0 1px 3px #17201a0a}.ct[data-v-1a353dab]{display:flex;align-items:center;gap:8px;margin-bottom:10px}.ct .dim[data-v-1a353dab]{font-size:11.5px;color:var(--dim)}.pn-tag.new[data-v-1a353dab]{background:#1a9d5f1f;color:var(--green)}.card h3[data-v-1a353dab]{font-family:var(--serif);font-size:17px;line-height:1.62;font-weight:600;color:var(--ink);margin-bottom:12px}.sum[data-v-1a353dab]{font-size:13px;line-height:1.8;color:var(--dim);margin-bottom:10px}.src[data-v-1a353dab]{font-size:12px;line-height:1.85;color:var(--dim);padding:9px 12px;border-left:2px solid var(--line);background:#17201a06;margin-bottom:14px;white-space:pre-wrap}.hint[data-v-1a353dab]{font-size:12px;color:var(--dim);margin:4px 0 14px;line-height:1.7}.err[data-v-1a353dab]{margin-top:10px;font-size:11px;color:#b4453c}.act[data-v-1a353dab]{display:inline-block;padding:8px 18px;border-radius:var(--r-pill);font-size:12px;font-weight:600;color:#fff;background:var(--green);transition:opacity .15s}.act[data-v-1a353dab]:hover{opacity:.9}.grades[data-v-1a353dab]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}.g[data-v-1a353dab]{display:flex;flex-direction:column;align-items:center;gap:2px;padding:9px 4px 8px;border-radius:var(--r-sm);font-size:12px;font-weight:600;color:var(--ink);background:#ffffffe6;border:1px solid var(--line-soft);transition:border-color .14s,background .14s,color .14s}.g span[data-v-1a353dab]{font-size:11px;font-weight:500;color:var(--dim)}.g[data-v-1a353dab]:hover{border-color:#1a9d5f6b;background:#1a9d5f0f}.g0[data-v-1a353dab]:hover{border-color:#b4453c6b;background:#b4453c0f}.done[data-v-1a353dab],.idle[data-v-1a353dab]{padding:14px 2px}.done b[data-v-1a353dab]{font-size:13px}.done p[data-v-1a353dab],.idle p[data-v-1a353dab]{font-size:12px;line-height:1.8;color:var(--dim);margin:6px 0 14px}.idle b[data-v-1a353dab]{color:var(--ink)}.curve[data-v-1a353dab]{display:block;width:100%;height:130px;overflow:visible}.curve .ref[data-v-1a353dab]{stroke:#17201a1f;stroke-width:1;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.curve .line[data-v-1a353dab]{fill:none;stroke:var(--green);stroke-width:1.8;vector-effect:non-scaling-stroke}.curve .dot[data-v-1a353dab]{fill:var(--green);stroke:#fff;stroke-width:1.5;vector-effect:non-scaling-stroke}.axis[data-v-1a353dab]{display:flex;justify-content:space-between;align-items:baseline;margin-top:5px;font-size:11px;font-weight:600;color:var(--dim)}.axis .dim[data-v-1a353dab]{font-family:var(--mono);font-size:11px}.note[data-v-1a353dab]{margin-top:8px;font-size:11.5px;line-height:1.75;color:var(--dim)}.note.warn[data-v-1a353dab]{padding:7px 9px;border-radius:var(--r-sm);background:#c48a1a12;border-left:2px solid rgba(196,138,26,.45);color:#8a6a24}.load[data-v-1a353dab]{display:flex;align-items:flex-end;gap:6px;padding:8px 2px 0}.load .bar[data-v-1a353dab]{flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;min-width:0}.load i[data-v-1a353dab]{display:block;width:100%;max-width:26px;border-radius:2px 2px 0 0;background:#1a9d5f8c}.load i.zero[data-v-1a353dab]{background:#17201a24}.load span[data-v-1a353dab]{font-size:10.5px;color:var(--dim)}.load em[data-v-1a353dab]{font-style:normal;font-family:var(--mono);font-size:10.5px;font-weight:600;color:var(--ink)}.sec-gap[data-v-6518b64e]{margin-top:14px}.del[data-v-6518b64e]{flex-shrink:0;padding:4px 10px;border-radius:var(--r-pill);font-size:11px;font-weight:600;color:var(--dim);background:var(--surface-2);border:1px solid var(--line-soft)}.del[data-v-6518b64e]:hover{color:var(--red);background:#e5484d1a}.del[data-v-6518b64e]:disabled{opacity:.5}.card[data-v-01d0339a]{border-radius:var(--r-mid);background:#ffffffd1;border:1px solid var(--line-soft);box-shadow:0 1px 2px #17201a0a;padding:4px 6px 6px;margin-bottom:12px}.grp[data-v-01d0339a]{padding:8px 8px 6px;font-size:11px;font-weight:700;letter-spacing:.08em;color:var(--dim);text-transform:uppercase}.row[data-v-01d0339a]{width:100%;display:flex;align-items:center;gap:10px;padding:8px;border-radius:var(--r-sm);text-align:left;transition:background .14s}.row[data-v-01d0339a]:hover{background:#ffffffe6}.row.static[data-v-01d0339a]:hover{background:transparent}.row .ic[data-v-01d0339a]{width:22px;height:22px;display:grid;place-items:center;color:var(--dim);flex-shrink:0}.row .ic svg[data-v-01d0339a]{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.row .m[data-v-01d0339a]{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.row .m b[data-v-01d0339a]{font-size:13px;font-weight:600;color:var(--ink)}.row .m span[data-v-01d0339a]{font-size:11.5px;color:var(--dim)}.hint[data-v-01d0339a]{display:flex;align-items:center;gap:5px;font-size:12px;font-weight:600;color:var(--dim);flex-shrink:0}.hint .dot[data-v-01d0339a]{width:7px;height:7px;border-radius:50%}.chev[data-v-01d0339a]{color:var(--dim);font-size:13px;flex-shrink:0;transition:transform .16s}.chev.open[data-v-01d0339a]{transform:rotate(90deg)}.seg[data-v-01d0339a]{display:flex;gap:2px;padding:2px;border-radius:var(--r-sm);background:#17201a0d;flex-shrink:0}.seg button[data-v-01d0339a]{padding:4px 10px;border-radius:7px;font-size:11.5px;color:var(--dim);transition:background .15s,color .15s}.seg button.on[data-v-01d0339a]{background:#fff;color:var(--ink);font-weight:600;box-shadow:0 1px 2px #17201a12}.sub[data-v-01d0339a]{margin:2px 8px 6px 40px;padding:4px;border-left:1px solid var(--line-soft)}.opt[data-v-01d0339a]{width:100%;display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:7px;text-align:left;transition:background .13s}.opt[data-v-01d0339a]:hover{background:#ffffffe6}.opt.on[data-v-01d0339a]{background:#1a9d5f17}.opt .dot[data-v-01d0339a]{width:7px;height:7px;border-radius:50%;flex-shrink:0}.opt .m[data-v-01d0339a]{flex:1;min-width:0;display:flex;align-items:baseline;gap:7px}.opt .m b[data-v-01d0339a]{font-size:12.5px;font-weight:600;color:var(--ink)}.opt .m span[data-v-01d0339a]{font-size:11.5px;color:var(--dim);font-family:var(--mono)}.tip[data-v-01d0339a]{padding:4px 8px 2px;font-size:11.5px;line-height:1.6;color:var(--dim)}.tip.err[data-v-01d0339a]{color:var(--red)}.nick-edit[data-v-01d0339a]{display:flex;align-items:center;gap:6px;padding:4px 8px 2px}.nick-in[data-v-01d0339a]{flex:1;min-width:0;padding:5px 8px;border-radius:7px;font-size:12.5px;color:var(--ink);background:#fff;border:1px solid var(--line)}.nick-in[data-v-01d0339a]:focus{outline:none;border-color:#1a9d5f80}.nick-save[data-v-01d0339a]{flex-shrink:0;padding:5px 11px;border-radius:7px;font-size:12px;font-weight:600;color:#fff;background:var(--green)}.nick-save[data-v-01d0339a]:disabled{opacity:.45}.kv[data-v-01d0339a]{display:flex;align-items:center;gap:10px;padding:4px 8px}.kv kbd[data-v-01d0339a]{min-width:92px;flex-shrink:0;font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--ink);padding:2px 6px;border-radius:5px;background:#17201a0d}.kv span[data-v-01d0339a]{font-size:11.5px;color:var(--dim)}.foot[data-v-01d0339a]{display:flex;align-items:center;justify-content:space-between;margin-top:2px;padding:10px 4px 2px;border-top:1px solid var(--line-soft)}.foot .mono[data-v-01d0339a]{font-family:var(--mono);font-size:11.5px;color:var(--dim)}.foot .dev[data-v-01d0339a]{font-size:12px;color:var(--faint)}.stage[data-v-31f35103]{display:flex;flex-direction:column;min-height:0}.tabs[data-v-31f35103]{display:flex;align-items:center;gap:4px;padding:8px 10px 0;flex-shrink:0;overflow-x:auto}.tab[data-v-31f35103]{display:flex;align-items:center;gap:6px;padding:6px 11px;border-radius:var(--r-sm) var(--r-sm) 0 0;font-size:12px;color:var(--dim);border:1px solid transparent;border-bottom:0;white-space:nowrap}.tab[data-v-31f35103]:hover{color:var(--ink);background:#ffffff80}.tab.on[data-v-31f35103]{color:var(--ink);font-weight:600;background:#ffffffdb;border-color:var(--line-soft)}.tab.doc[data-v-31f35103]{max-width:260px}.tab.doc .t[data-v-31f35103]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab.doc .x[data-v-31f35103]{font-size:11px;color:var(--dim)}.tab.doc .x[data-v-31f35103]:hover{color:var(--red)}.stage-body[data-v-31f35103]{flex:1;min-height:0;margin:0 8px 8px;border-radius:0 var(--r-mid) var(--r-mid) var(--r-mid);background:var(--mid-panel);border:1px solid rgba(26,157,95,.1);overflow:hidden;display:flex}.stage-body.bare[data-v-31f35103]{margin-top:8px;border-radius:var(--r-mid)}.core[data-v-31f35103]{flex:1;min-height:0;display:flex;flex-direction:column}.core-empty[data-v-31f35103]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;position:relative;padding:24px 18px;overflow-y:auto}.core-cap[data-v-31f35103]{font-size:12.5px;color:var(--dim);line-height:1.7;text-align:center}.hero[data-v-31f35103]{text-align:center}.hero-t[data-v-31f35103]{font-size:19px;font-weight:600;letter-spacing:-.02em;color:var(--ink);margin-bottom:6px}.ask-nick[data-v-31f35103]{display:flex;align-items:center;gap:8px;width:100%;max-width:420px;padding:9px 11px;border-radius:var(--r-sm);background:#1a9d5f0f;border:1px solid rgba(26,157,95,.22)}.an-q[data-v-31f35103]{font-size:12.5px;font-weight:600;color:var(--ink);flex-shrink:0}.an-in[data-v-31f35103]{flex:1;min-width:56px;padding:5px 8px;border-radius:7px;font-size:12.5px;color:var(--ink);background:#fff;border:1px solid var(--line)}.an-in[data-v-31f35103]:focus{outline:none;border-color:#1a9d5f80}.an-ok[data-v-31f35103]{flex-shrink:0;padding:5px 10px;border-radius:7px;font-size:12px;font-weight:600;color:#fff;background:var(--green)}.an-ok[data-v-31f35103]:disabled{opacity:.45;cursor:default}.an-skip[data-v-31f35103]{flex-shrink:0;padding:4px 2px;font-size:11.5px;color:var(--dim)}.an-skip[data-v-31f35103]:hover{color:var(--ink)}.tries[data-v-31f35103]{display:flex;flex-direction:column;gap:6px;width:100%;max-width:420px}.try[data-v-31f35103]{display:flex;align-items:center;gap:8px;width:100%;padding:10px 13px;border-radius:var(--r-sm);font-size:12.5px;color:var(--ink);text-align:left;background:#ffffffd1;border:1px solid var(--line);transition:color .14s,border-color .14s,background .14s,transform .12s}.try[data-v-31f35103]:hover{color:var(--ink);background:#fff;border-color:#1a9d5f6b}.try[data-v-31f35103]:active{transform:scale(.99)}.try .arrow[data-v-31f35103]{font-size:12px;color:var(--green);flex-shrink:0}.resume[data-v-31f35103]{display:flex;align-items:center;gap:7px;max-width:420px;padding:7px 13px;border-radius:var(--r-pill);background:var(--surface-2);color:var(--dim);transition:background .14s,color .14s}.resume[data-v-31f35103]:hover{background:var(--surface-3);color:var(--ink)}.resume .rl[data-v-31f35103]{font-size:11px;font-weight:700;color:var(--dim);text-transform:uppercase;letter-spacing:.07em}.resume b[data-v-31f35103]{font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.resume .rm[data-v-31f35103]{font-size:11px;color:var(--dim);flex-shrink:0}.recent[data-v-31f35103]{width:100%;max-width:420px}.recent .rh[data-v-31f35103]{margin-bottom:5px;font-size:11px;font-weight:700;letter-spacing:.08em;color:var(--dim);text-transform:uppercase}.rk-list[data-v-31f35103]{display:flex;flex-wrap:wrap;gap:5px}.rk[data-v-31f35103]{max-width:190px;padding:5px 10px;border-radius:var(--r-pill);font-size:11.5px;color:var(--ink);background:#fffc;border:1px solid var(--line);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:color .13s,border-color .13s,background .13s}.rk[data-v-31f35103]:hover{color:var(--green);background:#fff;border-color:#1a9d5f66}.cm[data-v-d6468d56]{position:absolute;left:8px;right:8px;bottom:calc(100% + 6px);z-index:40;max-height:264px;overflow-y:auto;padding:5px;border-radius:var(--r-mid);background:#fffffff0;-webkit-backdrop-filter:blur(24px) saturate(180%);backdrop-filter:blur(24px) saturate(180%);border:1px solid rgba(255,255,255,.9);box-shadow:var(--sh-pop);animation:cm-in-d6468d56 .13s ease}@keyframes cm-in-d6468d56{0%{opacity:0;transform:translateY(4px)}}.cm-h[data-v-d6468d56]{padding:4px 7px 5px;font-size:11px;font-weight:700;letter-spacing:.07em;color:var(--dim);text-transform:uppercase}.cm-it[data-v-d6468d56]{width:100%;display:flex;align-items:baseline;gap:8px;padding:7px 9px;border-radius:var(--r-sm);text-align:left}.cm-it.on[data-v-d6468d56]{background:var(--surface-2)}.cm-it b[data-v-d6468d56]{font-size:12.5px;font-weight:700;font-family:var(--mono);flex-shrink:0;color:var(--ink)}.cm-it span[data-v-d6468d56]{flex:1;min-width:0;font-size:12px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cm-it em[data-v-d6468d56]{font-style:normal;font-size:10.5px;font-weight:600;color:var(--dim);padding:2px 6px;border-radius:var(--r-pill);background:var(--surface-2)}.cm-empty[data-v-d6468d56]{padding:10px 8px;font-size:12px;color:var(--dim)}.cm-f[data-v-d6468d56]{padding:7px 8px 3px;margin-top:3px;border-top:1px solid var(--line-soft);font-size:11px;color:var(--dim);font-family:var(--mono)}.mp[data-v-1c7db88f]{position:relative;flex-shrink:0}.pill[data-v-1c7db88f]{display:flex;align-items:center;gap:5px;padding:5px 9px;border-radius:var(--r-pill);font-size:12px;font-weight:600;color:var(--ink);background:var(--surface-2);max-width:150px;transition:background .15s,color .15s}.pill[data-v-1c7db88f]:hover,.pill.on[data-v-1c7db88f]{background:var(--surface-3);color:var(--ink)}.pill .dot[data-v-1c7db88f]{width:5px;height:5px;border-radius:50%;flex-shrink:0}.pill .nm[data-v-1c7db88f]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pill .caret[data-v-1c7db88f]{font-size:10px;color:var(--dim)}.pop[data-v-1c7db88f]{position:absolute;left:0;bottom:calc(100% + 8px);z-index:var(--z-menu);width:272px;max-height:54vh;display:flex;flex-direction:column;padding:6px;border-radius:var(--r-mid);background:#ffffffeb;-webkit-backdrop-filter:blur(24px) saturate(180%);backdrop-filter:blur(24px) saturate(180%);border:1px solid rgba(255,255,255,.9);box-shadow:var(--sh-pop);overflow-y:auto;animation:mp-in-1c7db88f .15s ease}@keyframes mp-in-1c7db88f{0%{opacity:0;transform:translateY(5px)}}.it[data-v-1c7db88f]{width:100%;display:flex;align-items:center;gap:8px;padding:6px 7px;border-radius:var(--r-sm);text-align:left;transition:background .13s}.it[data-v-1c7db88f]:hover{background:var(--surface-2)}.it.on[data-v-1c7db88f]{background:var(--accent-soft)}.it.dis[data-v-1c7db88f]{opacity:.55}.it .dot[data-v-1c7db88f]{width:6px;height:6px;border-radius:50%;flex-shrink:0}.it .tx[data-v-1c7db88f]{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.it .tx b[data-v-1c7db88f]{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.it .tx span[data-v-1c7db88f]{font-size:11px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.it .tx.plain[data-v-1c7db88f]{background:none;padding:0}.tg[data-v-1c7db88f]{flex-shrink:0;font-size:10.5px;font-weight:600;padding:2px 6px;border-radius:var(--r-pill);color:var(--accent);background:#1a9d5f21}.tg.warn[data-v-1c7db88f]{color:var(--amber);background:#c88c2821}.it .x[data-v-1c7db88f]{flex-shrink:0;font-size:11px;color:var(--dim);padding:2px 4px}.it .x[data-v-1c7db88f]:hover{color:var(--red)}button.x[data-v-1c7db88f]{background:none;border:0;font-family:inherit;cursor:pointer}button.x[data-v-1c7db88f]:hover:not(:disabled){color:var(--accent)}button.x[data-v-1c7db88f]:disabled{opacity:.4;cursor:default}.tres[data-v-1c7db88f]{margin-top:5px;padding:7px 9px;border-radius:var(--r-sm);font-size:11.5px;line-height:1.55;color:var(--dim);background:var(--surface-2);overflow-wrap:anywhere}.tres.ok[data-v-1c7db88f]{color:var(--green);background:#1a9d5f14}.tres.err[data-v-1c7db88f]{color:var(--red);background:#e5484d12}.sep[data-v-1c7db88f]{padding:9px 7px 4px;font-size:11px;font-weight:700;letter-spacing:.08em;color:var(--dim);text-transform:uppercase}.empty[data-v-1c7db88f]{padding:10px 7px;font-size:12px;color:var(--dim)}.foot[data-v-1c7db88f]{position:sticky;bottom:-6px;display:flex;gap:5px;padding:6px 4px 4px;margin-top:5px;border-top:1px solid var(--line-soft);background:#fffffff5;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.fbtn[data-v-1c7db88f]{flex:1;padding:7px;border-radius:var(--r-sm);font-size:12px;font-weight:600;color:var(--dim);background:var(--surface-2)}.fbtn[data-v-1c7db88f]:hover{color:var(--ink);background:var(--surface-3)}.form[data-v-1c7db88f]{display:flex;flex-direction:column;gap:6px;padding:4px}.fhead[data-v-1c7db88f]{display:flex;align-items:center;justify-content:space-between;font-size:12.5px;font-weight:700;padding:2px 3px 4px}.fhead .x[data-v-1c7db88f]{cursor:pointer;color:var(--dim);font-size:12px}.form label[data-v-1c7db88f]{display:flex;flex-direction:column;gap:3px;font-size:11.5px;font-weight:600;color:var(--dim)}.form input[data-v-1c7db88f]{padding:6px 8px;border-radius:7px;font-size:12px;background:#fff;border:1px solid var(--line)}.form input[data-v-1c7db88f]:focus{border-color:#1a9d5f73}.form input[data-v-1c7db88f]:disabled{color:var(--faint);background:var(--surface-2)}.submit[data-v-1c7db88f]{margin-top:3px;padding:7px;border-radius:var(--r-sm);font-size:12px;font-weight:600;color:#fff;background:var(--green)}.submit[data-v-1c7db88f]:disabled{opacity:.6}.tm[data-v-28d25609]{position:relative;flex-shrink:0}.plus[data-v-28d25609]{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-size:15px;color:var(--dim);background:var(--surface-2);transition:color .15s,background .15s}.plus[data-v-28d25609]:hover,.plus.on[data-v-28d25609]{color:var(--ink);background:var(--surface-3)}.pop[data-v-28d25609]{position:absolute;left:0;bottom:calc(100% + 8px);z-index:var(--z-menu);width:250px;max-height:54vh;display:flex;flex-direction:column;padding:6px;border-radius:var(--r-mid);background:#ffffffeb;-webkit-backdrop-filter:blur(24px) saturate(180%);backdrop-filter:blur(24px) saturate(180%);border:1px solid rgba(255,255,255,.9);box-shadow:var(--sh-pop);overflow-y:auto;animation:tm-in-28d25609 .15s ease}@keyframes tm-in-28d25609{0%{opacity:0;transform:translateY(5px)}}.sec[data-v-28d25609]{padding:6px 7px 4px;font-size:11px;font-weight:700;letter-spacing:.08em;color:var(--dim);text-transform:uppercase}.it[data-v-28d25609]{width:100%;display:flex;align-items:center;gap:9px;padding:8px;border-radius:var(--r-sm);text-align:left;transition:background .13s}.it[data-v-28d25609]:hover{background:var(--surface-2)}.it .ic[data-v-28d25609]{font-size:14px;width:16px;text-align:center;flex-shrink:0}.it .tx[data-v-28d25609]{display:flex;flex-direction:column;gap:2px}.it .tx b[data-v-28d25609]{font-size:13px;font-weight:600}.it .tx span[data-v-28d25609]{font-size:11px;color:var(--dim)}.foot[data-v-28d25609]{margin-top:4px;padding:7px 7px 3px;border-top:1px solid var(--line-soft);font-size:11px;color:var(--dim);font-family:var(--mono)}.dock[data-v-371234e7]{padding:0 8px 8px;position:relative}.dock-in[data-v-371234e7]{position:relative;width:min(736px,calc(100% - 44px));margin:0 auto}.chips[data-v-371234e7]{display:flex;gap:6px;flex-wrap:wrap;padding:0 2px 7px}.chip[data-v-371234e7]{display:flex;align-items:center;gap:6px;padding:5px 9px;border-radius:var(--r-pill);font-size:11.5px;background:#ffffffe6;border:1px solid var(--line);box-shadow:0 1px 2px #17201a0a;max-width:220px}.chip .cn[data-v-371234e7]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}.chip .cs[data-v-371234e7]{font-family:var(--mono);font-size:10.5px;color:var(--dim);flex-shrink:0}.chip .cx[data-v-371234e7]{cursor:pointer;font-size:11px;color:var(--dim);padding:0 2px;flex-shrink:0}.chip .cx[data-v-371234e7]:hover{color:var(--red)}.chip.img[data-v-371234e7]{padding:3px 5px}.chip.img img[data-v-371234e7]{width:22px;height:22px;border-radius:5px;object-fit:cover}.chip.ing[data-v-371234e7]{border-color:#1a9d5f4d}.chip.ing.error[data-v-371234e7]{border-color:#c83c3c57}.chip.ing .bar[data-v-371234e7]{width:44px;height:3px;border-radius:2px;overflow:hidden;background:#17201a1a;flex-shrink:0}.chip.ing .bar i[data-v-371234e7]{display:block;height:100%;background:var(--green);transition:width .3s}.chip.ing.error .bar i[data-v-371234e7]{background:var(--red)}.wrap[data-v-371234e7]{display:flex;align-items:flex-end;gap:8px;padding:7px 9px;background:#ffffffe6;border:1px solid var(--line-soft);border-radius:var(--r-mid);box-shadow:var(--sh-card);transition:border-color .15s,box-shadow .15s}.wrap[data-v-371234e7]:focus-within{border-color:#1a9d5f66;box-shadow:0 0 0 3px #1a9d5f14,var(--sh-card)}textarea[data-v-371234e7]{flex:1;min-width:0;font-size:13.5px;line-height:1.6;padding:5px 2px;border:0;background:none;resize:none;overflow-y:auto;max-height:340px;transition:height .14s ease}textarea[data-v-371234e7]:focus{outline:none}textarea[data-v-371234e7]::placeholder{color:var(--dim);opacity:1}.send[data-v-371234e7]{width:30px;height:30px;border-radius:50%;flex-shrink:0;display:grid;place-items:center;font-size:12px;color:#fff;background:var(--green);box-shadow:0 4px 12px #1a9d5f4d;transition:transform .1s,filter .15s,background .15s}.send[data-v-371234e7]:hover{filter:brightness(1.06)}.send[data-v-371234e7]:active{transform:scale(.94)}.send.stop[data-v-371234e7]{background:var(--red);box-shadow:0 4px 12px #e5484d47;font-size:10px}.toast[data-v-371234e7]{position:absolute;left:50%;bottom:62px;transform:translate(-50%);padding:7px 13px;border-radius:var(--r-pill);font-size:11.5px;color:var(--cli-ink);background:#11160feb;box-shadow:var(--sh-pop);white-space:nowrap;max-width:82vw;overflow:hidden;text-overflow:ellipsis;z-index:30}.fade-enter-active[data-v-371234e7],.fade-leave-active[data-v-371234e7]{transition:opacity .18s}.fade-enter-from[data-v-371234e7],.fade-leave-to[data-v-371234e7]{opacity:0}.qi[data-v-6cdbc607]{padding:0 0 10px;margin-bottom:14px;border-bottom:1px solid var(--line-soft)}.qi-h[data-v-6cdbc607]{display:flex;align-items:baseline;gap:6px;margin-bottom:7px;font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--dim)}.qi-h em[data-v-6cdbc607]{font-style:normal;font-weight:500;letter-spacing:0;text-transform:none;font-size:11px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.qi-ta[data-v-6cdbc607]{display:block;width:100%;box-sizing:border-box;resize:vertical;min-height:46px;max-height:140px;padding:7px 9px;border-radius:var(--r-sm);font-family:var(--sans);font-size:12.5px;line-height:1.6;color:var(--ink);background:#fff;border:1px solid var(--line);transition:border-color .15s}.qi-ta[data-v-6cdbc607]::placeholder{color:var(--dim)}.qi-ta[data-v-6cdbc607]:focus{outline:none;border-color:#1a9d5f6b}.qi-b[data-v-6cdbc607]{display:flex;gap:6px;margin-top:6px}.qi-title[data-v-6cdbc607]{flex:1 1 auto;min-width:0;padding:5px 8px;border-radius:var(--r-pill);font-size:11.5px;color:var(--ink);background:#ffffffdb;border:1px solid var(--line)}.qi-title[data-v-6cdbc607]::placeholder{color:var(--dim)}.qi-title[data-v-6cdbc607]:focus{outline:none;border-color:#1a9d5f59}.qi-go[data-v-6cdbc607]{flex-shrink:0;padding:6px 13px;border-radius:var(--r-pill);font-size:11.5px;font-weight:600;color:#fff;background:var(--green);border:1px solid var(--green);transition:opacity .15s}.qi-go[data-v-6cdbc607]:disabled{background:#17201a12;color:var(--dim);border-color:var(--line)}.qi-msg[data-v-6cdbc607]{margin-top:6px;font-size:11px;line-height:1.5}.qi-msg.ok[data-v-6cdbc607]{color:var(--green)}.qi-msg.busy[data-v-6cdbc607]{color:var(--dim)}.qi-msg.err[data-v-6cdbc607]{color:#b4453c}.rail-right[data-v-6327fda1]{padding:0}.head[data-v-6327fda1]{display:flex;align-items:center;gap:8px;flex-shrink:0;padding:10px 12px 9px;border-bottom:1px solid var(--line-soft)}.seg[data-v-6327fda1]{display:flex;gap:2px;padding:2px;border-radius:var(--r-sm);background:#4032200e}.seg button[data-v-6327fda1]{display:flex;align-items:center;gap:4px;padding:4px 11px;border-radius:7px;font-size:11.5px;color:var(--dim);transition:background .15s,color .15s}.seg button.on[data-v-6327fda1]{background:#fff;color:var(--ink);font-weight:600;box-shadow:0 1px 2px #40322017}.seg .pip[data-v-6327fda1]{width:5px;height:5px;border-radius:50%;background:var(--green)}.collapse[data-v-6327fda1]{margin-left:auto;font-size:13px;color:var(--faint);padding:2px 5px}.collapse[data-v-6327fda1]:hover{color:var(--ink)}.body[data-v-6327fda1]{flex:1;padding:12px}.sec[data-v-6327fda1]{margin-bottom:20px}.sec-h[data-v-6327fda1]{display:flex;align-items:center;justify-content:space-between;font-size:11.5px;font-weight:700;letter-spacing:.07em;color:var(--dim);text-transform:uppercase;margin-bottom:8px}.sec-h em[data-v-6327fda1]{font-family:var(--mono);font-size:11.5px;font-weight:700;color:var(--ink)}.kpi[data-v-6327fda1]{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px}.kpi div[data-v-6327fda1]{padding:8px 9px;border-radius:var(--r-sm);background:#ffffffe6;border:1px solid var(--line)}.kpi b[data-v-6327fda1]{display:block;font-size:16px;font-weight:700;letter-spacing:-.01em;color:var(--w-ink)}.kpi span[data-v-6327fda1]{font-size:11.5px;font-weight:500;color:var(--w-dim)}.go[data-v-6327fda1]{width:100%;padding:8px;border-radius:var(--r-sm);font-size:12px;font-weight:600;color:#fff;background:var(--green);transition:opacity .15s}.go[data-v-6327fda1]:disabled{color:var(--w-dim);background:#40322012;font-weight:600;border:1px solid var(--line-soft)}.go[data-v-6327fda1]:not(:disabled):hover{opacity:.9}.sub-h[data-v-6327fda1]{display:flex;justify-content:space-between;padding:5px 2px 6px;font-size:11px;font-weight:600;color:var(--w-dim)}.sub-h em[data-v-6327fda1]{font-style:normal;font-family:var(--mono)}.row[data-v-6327fda1]{width:100%;text-align:left;display:flex;flex-direction:column;gap:2px;padding:8px 9px;border-radius:var(--r-sm);margin-bottom:2px;transition:background .14s}.row[data-v-6327fda1]:hover{background:#ffffffbf}.row b[data-v-6327fda1]{font-size:13px;font-weight:600;color:var(--w-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row span[data-v-6327fda1]{font-size:11.5px;color:var(--w-dim)}.more[data-v-6327fda1]{width:100%;display:flex;align-items:center;justify-content:center;gap:6px;margin-top:4px;padding:7px 9px;border-radius:var(--r-sm);font-size:12px;font-weight:600;color:var(--w-dim);border:1px dashed var(--line);transition:color .15s,border-color .15s,background .15s}.more[data-v-6327fda1]:hover{color:var(--green);border-color:#1a9d5f52;background:#1a9d5f0d}.bars[data-v-6327fda1]{display:flex;flex-direction:column;gap:2px}.bars i[data-v-6327fda1]{display:block;width:10px;height:1.5px;border-radius:1px;background:currentColor;opacity:.75}.doc-head[data-v-6327fda1]{padding:0 4px 12px;border-bottom:1px solid var(--line-soft);margin-bottom:12px}.kind[data-v-6327fda1]{display:inline-block;margin-bottom:7px;padding:3px 8px;border-radius:var(--r-pill);font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.08em}.kind.code[data-v-6327fda1]{background:var(--cli-bg);color:var(--cli-acc)}.kind.text[data-v-6327fda1]{background:var(--surface-2);color:var(--w-ink)}.doc-head h3[data-v-6327fda1]{font-size:15px;font-weight:650;line-height:1.45;color:var(--w-ink)}.path[data-v-6327fda1]{display:block;margin-top:6px;font-family:var(--mono);font-size:11px;color:var(--w-dim);word-break:break-all}.meta[data-v-6327fda1]{margin-top:5px;font-size:11.5px;color:var(--w-dim)}.out-line[data-v-6327fda1]{display:flex;gap:7px;padding:6px 7px;border-radius:7px;font-size:12px;color:var(--w-ink);line-height:1.55}.out-line[data-v-6327fda1]:hover{background:#ffffffb3;color:var(--w-ink)}.out-line .n[data-v-6327fda1]{font-family:var(--mono);font-size:10.5px;color:var(--w-dim);padding-top:2px}.acts[data-v-6327fda1]{padding-top:6px}.acts button[data-v-6327fda1]{width:100%;padding:8px;border-radius:var(--r-sm);font-size:12.5px;font-weight:600;color:var(--w-ink);background:#fffc;border:1px solid var(--line)}.acts button[data-v-6327fda1]:hover{color:var(--ink);background:#fff}:root{--g-left: #d7e8d0;--g-mid: #eef7e8;--g-right: #f8f3e9;--band: linear-gradient(100deg, var(--g-left) 0%, var(--g-mid) 46%, var(--g-right) 100%);--veil-left: rgba(255, 255, 255, .28);--veil-mid: rgba(236, 246, 228, .9);--veil-right: rgba(251, 247, 239, .92);--mid-panel: rgba(238, 247, 232, .95);--right-panel: #fbf7ef;--ink: #17201a;--dim: #3f4c42;--faint: #65716a;--line: rgba(23, 32, 26, .1);--line-soft: rgba(23, 32, 26, .06);--w-ink: #211d17;--w-dim: #4a4237;--w-faint: #776d5c;--w-line: rgba(64, 50, 32, .12);--w-line-soft: rgba(64, 50, 32, .06);--w-surface-2: #f3ede1;--w-surface-3: #e9e1d2;--accent: #0a84ff;--accent-soft: rgba(10, 132, 255, .1);--green: #1a9d5f;--amber: #c77400;--red: #e5484d;--surface: #ffffff;--surface-2: #f1f4ef;--surface-3: #e4eae2;--r-card: 20px;--r-mid: 14px;--r-sm: 10px;--r-pill: 999px;--sh-card: 0 1px 2px rgba(23, 32, 26, .04), 0 10px 26px rgba(23, 32, 26, .07);--sh-pop: 0 14px 40px rgba(23, 32, 26, .18), 0 2px 10px rgba(23, 32, 26, .08);--gap: 14px;--pad: 14px;--cli-bg: #11160f;--cli-bg-2: #0b0f0a;--cli-ink: #d9e6d2;--cli-dim: #849480;--cli-line: rgba(255, 255, 255, .07);--cli-acc: #7fe08c;--cli-warn: #e2c07a;--font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;--mono: ui-monospace, SFMono-Regular, "JetBrains Mono", "Cascadia Code", Consolas, monospace;--serif: "Songti SC", "Noto Serif SC", Georgia, serif;--z-menu: 100;--z-top: 500}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body,#app{height:100%}body{font-family:var(--font);color:var(--ink);background:var(--g-right);-webkit-font-smoothing:antialiased;overflow:hidden}button{font-family:inherit;border:0;background:none;color:inherit;cursor:pointer}input,textarea{font-family:inherit;border:0;background:none;color:inherit;outline:none}em{font-style:normal}.app{height:100vh;display:grid;grid-template-rows:56px 1fr;min-height:0}.workspace{--rail-w: 344px;display:grid;grid-template-columns:296px minmax(0,1fr) var(--rail-w);gap:var(--gap);padding:var(--pad);min-height:0;background:var(--band);transition:grid-template-columns .24s ease}.workspace.is-collapsed{--rail-w: 0px}.col{position:relative;display:flex;flex-direction:column;min-height:0;min-width:0;border-radius:var(--r-card);border:1px solid rgba(255,255,255,.55);background:var(--veil-left);-webkit-backdrop-filter:blur(16px) saturate(150%);backdrop-filter:blur(16px) saturate(150%);box-shadow:var(--sh-card);overflow:hidden}.col--mid{background:var(--veil-mid)}.col--right{background:var(--right-panel);--ink: var(--w-ink);--dim: var(--w-dim);--faint: var(--w-faint);--line: var(--w-line);--line-soft: var(--w-line-soft);--surface-2: var(--w-surface-2);--surface-3: var(--w-surface-3);transition:opacity .18s ease}.col--right .scroll::-webkit-scrollbar-thumb{background:#40322029}.workspace.is-collapsed .col--right{opacity:0;pointer-events:none}.mid{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto}.scroll{overflow-y:auto;overscroll-behavior:contain;min-height:0}.scroll::-webkit-scrollbar{width:8px;height:8px}.scroll::-webkit-scrollbar-thumb{background:#17201a24;border-radius:99px}.scroll::-webkit-scrollbar-track{background:transparent}.empty{padding:28px 12px;text-align:center;font-size:12.5px;color:var(--faint);line-height:1.7}.dot{width:6px;height:6px;border-radius:50%;background:var(--green);flex-shrink:0}.rail-handle{position:fixed;right:0;top:50%;transform:translateY(-50%);z-index:var(--z-menu);padding:16px 6px;font-size:11px;letter-spacing:.04em;color:var(--dim);background:#ffffffdb;border:1px solid var(--line);border-right:0;border-radius:12px 0 0 12px;box-shadow:var(--sh-card);writing-mode:vertical-rl}.rail-handle:hover{color:var(--ink)}@media(prefers-reduced-motion:reduce){.workspace,.col--right{transition:none}}@media(max-width:1180px){.workspace{grid-template-columns:248px minmax(0,1fr)}.col--right{position:fixed;top:calc(56px + var(--pad));right:var(--pad);bottom:var(--pad);width:344px;z-index:60;box-shadow:var(--sh-pop);transition:transform .2s ease,opacity .18s ease}.workspace.is-collapsed .col--right{transform:translate(calc(100% + var(--pad)))}}.rail-scrim{position:fixed;inset:56px 0 0;z-index:59;background:#17201a29}.pn-sec{margin-bottom:18px}.pn-sec:last-child{margin-bottom:0}.pn-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;font-size:11.5px;font-weight:700;letter-spacing:.07em;color:var(--dim);text-transform:uppercase}.pn-h em{font-style:normal;font-family:var(--mono);font-size:11.5px;font-weight:700;color:var(--ink);text-transform:none}.pn-kpi{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}.pn-kpi>div{flex:1 1 104px;padding:10px 11px;border-radius:var(--r-sm);background:#ffffffc7;border:1px solid var(--line-soft)}.pn-kpi b{display:block;font-size:18px;font-weight:650;letter-spacing:-.02em;line-height:1.25}.pn-kpi span{font-size:11.5px;font-weight:500;color:var(--dim)}.pn-row{width:100%;text-align:left;display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:var(--r-sm);border:1px solid transparent;transition:background .14s,border-color .14s}.pn-row+.pn-row{margin-top:2px}.pn-row:hover{background:#ffffffb8}.pn-row.clickable:hover{border-color:var(--line);background:#fff}.pn-row .m{flex:1;min-width:0}.pn-row b{display:block;font-size:13.5px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pn-row span.s{display:block;margin-top:2px;font-size:11.5px;color:var(--dim)}.pn-row .r{flex-shrink:0;font-family:var(--mono);font-size:11.5px;color:var(--dim)}.pn-tag{display:inline-block;flex-shrink:0;padding:3px 8px;border-radius:var(--r-pill);font-family:var(--mono);font-size:11px;letter-spacing:.04em;background:var(--surface-2);color:var(--dim)}.pn-tag.green{background:#1a9d5f1f;color:var(--green)}.pn-tag.amber{background:#c7740021;color:var(--amber)}.pn-tag.red{background:#e5484d1f;color:var(--red)}.pn-chips{display:flex;flex-wrap:wrap;gap:6px}.pn-chip{padding:5px 10px;border-radius:var(--r-pill);font-family:var(--mono);font-size:11.5px;color:var(--dim);background:#ffffffc7;border:1px solid var(--line-soft);transition:color .13s,border-color .13s,background .13s}button.pn-chip:hover{color:var(--green);background:#fff;border-color:#1a9d5f59}button.pn-chip.on{color:var(--green);background:#1a9d5f1a;border-color:#1a9d5f66}.pn-chip.warn{color:var(--amber);background:#c7740017;border-color:#c774003d}.pn-empty{padding:16px 12px;border-radius:var(--r-sm);font-size:12px;line-height:1.7;color:var(--dim);background:#fff9;border:1px dashed var(--line)}.pn-st{padding:14px 4px;font-size:12px;color:var(--dim)}.pn-st.err{color:var(--amber)}.pn-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px;align-items:start}.panel>.pb{container-type:inline-size}@container (max-width: 660px){.pn-cols{grid-template-columns:minmax(0,1fr);gap:0}}@container (max-width: 300px){.pn-row{flex-wrap:wrap;row-gap:6px}.pn-row .m{flex:1 1 100%}.pn-h{flex-wrap:wrap;gap:6px}.pn-kpi>div{flex:1 1 76px}}.pn-note{font-size:11.5px;line-height:1.65;color:var(--dim);padding:8px 10px;border-radius:var(--r-sm);background:#fff9;border:1px solid var(--line-soft)}.pn-note code{font-family:var(--mono);font-size:11px;color:var(--ink);word-break:break-all}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Foxclaw</title>
|
|
7
|
+
<!-- 内联 SVG 图标:不新增静态文件,也避免浏览器探 /favicon.ico 报 404 -->
|
|
8
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='9' fill='%23179d5f'/><circle cx='16' cy='16' r='6.5' fill='%23f4fbf0'/></svg>" />
|
|
9
|
+
<script type="module" crossorigin src="/v3/assets/index-CQSBdxk4.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/v3/assets/index-D5nIsjms.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="app"></div>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
|
|
2
|
+
const WidgetRuntime = (() => {
|
|
3
|
+
|
|
4
|
+
const registry = new Map();
|
|
5
|
+
|
|
6
|
+
let instances = [];
|
|
7
|
+
|
|
8
|
+
const eventSubs = new Map();
|
|
9
|
+
|
|
10
|
+
let ctx = {};
|
|
11
|
+
|
|
12
|
+
const columns = {};
|
|
13
|
+
|
|
14
|
+
function register(spec) {
|
|
15
|
+
if (!spec.id) throw new Error('widget 必须有 id');
|
|
16
|
+
registry.set(spec.id, {
|
|
17
|
+
defaultColumn: 'right',
|
|
18
|
+
size: { flex: false },
|
|
19
|
+
events: [],
|
|
20
|
+
render: () => {},
|
|
21
|
+
onEvent: null,
|
|
22
|
+
onAgentChange: null,
|
|
23
|
+
refresh: null,
|
|
24
|
+
...spec,
|
|
25
|
+
});
|
|
26
|
+
(spec.events || []).forEach(ev => {
|
|
27
|
+
if (!eventSubs.has(ev)) eventSubs.set(ev, new Set());
|
|
28
|
+
eventSubs.get(ev).add(spec.id);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function init(columnEls, sharedCtx) {
|
|
33
|
+
columns.left = columnEls.left;
|
|
34
|
+
columns.center = columnEls.center;
|
|
35
|
+
columns.right = columnEls.right;
|
|
36
|
+
ctx = sharedCtx || {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function setLayout(layout) {
|
|
40
|
+
instances = layout.map((item, i) => ({
|
|
41
|
+
instanceId: item.instanceId || `inst_${item.widgetId}_${i}`,
|
|
42
|
+
widgetId: item.widgetId,
|
|
43
|
+
column: item.column,
|
|
44
|
+
order: item.order != null ? item.order : i,
|
|
45
|
+
}));
|
|
46
|
+
renderAll();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function defaultLayout() {
|
|
50
|
+
return [...registry.values()].map((spec, i) => ({
|
|
51
|
+
instanceId: `inst_${spec.id}`,
|
|
52
|
+
widgetId: spec.id,
|
|
53
|
+
column: spec.defaultColumn,
|
|
54
|
+
order: i,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function renderAll() {
|
|
59
|
+
Object.values(columns).forEach(col => { if (col) col.innerHTML = ''; });
|
|
60
|
+
const byCol = { left: [], center: [], right: [] };
|
|
61
|
+
instances.forEach(inst => {
|
|
62
|
+
if (byCol[inst.column]) byCol[inst.column].push(inst);
|
|
63
|
+
});
|
|
64
|
+
Object.keys(byCol).forEach(colName => {
|
|
65
|
+
byCol[colName]
|
|
66
|
+
.sort((a, b) => a.order - b.order)
|
|
67
|
+
.forEach(inst => mountWidget(inst, colName));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function mountWidget(inst, colName) {
|
|
72
|
+
const spec = registry.get(inst.widgetId);
|
|
73
|
+
if (!spec) return;
|
|
74
|
+
const col = columns[colName];
|
|
75
|
+
if (!col) return;
|
|
76
|
+
|
|
77
|
+
const panel = document.createElement('div');
|
|
78
|
+
panel.className = 'panel';
|
|
79
|
+
panel.dataset.widget = inst.widgetId;
|
|
80
|
+
panel.dataset.instance = inst.instanceId;
|
|
81
|
+
if (spec.size.flex) panel.style.flex = '1';
|
|
82
|
+
if (spec.size.maxH) panel.style.maxHeight = spec.size.maxH + 'px';
|
|
83
|
+
|
|
84
|
+
panel.innerHTML = `
|
|
85
|
+
<div class="panel-corner-tr"></div><div class="panel-corner-bl"></div>
|
|
86
|
+
<div class="panel-head">
|
|
87
|
+
<span class="ph-icon">${spec.icon || '◈'}</span>
|
|
88
|
+
<span class="ph-title">${spec.title}</span>
|
|
89
|
+
<span class="ph-status" data-role="status"></span>
|
|
90
|
+
<span class="ph-drag" title="拖动">⠿</span>
|
|
91
|
+
<span class="ph-remove" title="移除" style="display:none">✕</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="panel-body" data-role="body"></div>`;
|
|
94
|
+
|
|
95
|
+
col.appendChild(panel);
|
|
96
|
+
|
|
97
|
+
const body = panel.querySelector('[data-role="body"]');
|
|
98
|
+
inst._el = panel;
|
|
99
|
+
inst._body = body;
|
|
100
|
+
|
|
101
|
+
panel.querySelector('.ph-remove').onclick = (e) => {
|
|
102
|
+
e.stopPropagation();
|
|
103
|
+
removeInstance(inst.instanceId);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
spec.render(body, ctx, inst);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
body.innerHTML = `<div class="empty">渲染错误: ${err.message}</div>`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (spec.onAgentChange && ctx.activeAgent) {
|
|
113
|
+
try { spec.onAgentChange(ctx.activeAgent, body, ctx); } catch {}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function dispatch(eventType, payload) {
|
|
118
|
+
const subscribers = eventSubs.get(eventType);
|
|
119
|
+
if (!subscribers) return;
|
|
120
|
+
instances.forEach(inst => {
|
|
121
|
+
if (!subscribers.has(inst.widgetId) || !inst._body) return;
|
|
122
|
+
const spec = registry.get(inst.widgetId);
|
|
123
|
+
if (spec.onEvent) {
|
|
124
|
+
try { spec.onEvent({ type: eventType, ...payload }, inst._body, ctx); } catch {}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function notifyAgentChange(agentId) {
|
|
130
|
+
ctx.activeAgent = agentId;
|
|
131
|
+
instances.forEach(inst => {
|
|
132
|
+
const spec = registry.get(inst.widgetId);
|
|
133
|
+
if (spec.onAgentChange && inst._body) {
|
|
134
|
+
try { spec.onAgentChange(agentId, inst._body, ctx); } catch {}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function refreshAll(agentId) {
|
|
140
|
+
instances.forEach(inst => {
|
|
141
|
+
const spec = registry.get(inst.widgetId);
|
|
142
|
+
if (spec.refresh && inst._body) {
|
|
143
|
+
try { spec.refresh(inst._body, ctx, agentId); } catch {}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function setStatus(instanceId, text) {
|
|
149
|
+
const inst = instances.find(i => i.instanceId === instanceId);
|
|
150
|
+
if (inst && inst._el) {
|
|
151
|
+
const s = inst._el.querySelector('[data-role="status"]');
|
|
152
|
+
if (s) s.textContent = text;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function addInstance(widgetId, column) {
|
|
157
|
+
const spec = registry.get(widgetId);
|
|
158
|
+
if (!spec) return;
|
|
159
|
+
const inst = {
|
|
160
|
+
instanceId: `inst_${widgetId}_${Date.now()}`,
|
|
161
|
+
widgetId,
|
|
162
|
+
column: column || spec.defaultColumn,
|
|
163
|
+
order: instances.length,
|
|
164
|
+
};
|
|
165
|
+
instances.push(inst);
|
|
166
|
+
renderAll();
|
|
167
|
+
saveLayout();
|
|
168
|
+
if (ctx.activeAgent) {
|
|
169
|
+
if (spec.onAgentChange) try { spec.onAgentChange(ctx.activeAgent, inst._body, ctx); } catch {}
|
|
170
|
+
if (spec.refresh) try { spec.refresh(inst._body, ctx, ctx.activeAgent); } catch {}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function removeInstance(instanceId) {
|
|
175
|
+
instances = instances.filter(i => i.instanceId !== instanceId);
|
|
176
|
+
renderAll();
|
|
177
|
+
saveLayout();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function captureLayoutFromDOM() {
|
|
181
|
+
const newInstances = [];
|
|
182
|
+
['left', 'center', 'right'].forEach(colName => {
|
|
183
|
+
const col = columns[colName];
|
|
184
|
+
if (!col) return;
|
|
185
|
+
[...col.children].forEach((panel, order) => {
|
|
186
|
+
const instanceId = panel.dataset.instance;
|
|
187
|
+
const widgetId = panel.dataset.widget;
|
|
188
|
+
const existing = instances.find(i => i.instanceId === instanceId);
|
|
189
|
+
newInstances.push({
|
|
190
|
+
instanceId,
|
|
191
|
+
widgetId,
|
|
192
|
+
column: colName,
|
|
193
|
+
order,
|
|
194
|
+
_el: panel,
|
|
195
|
+
_body: panel.querySelector('[data-role="body"]'),
|
|
196
|
+
...(existing ? {} : {}),
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
instances = newInstances;
|
|
201
|
+
saveLayout();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function saveLayout() {
|
|
205
|
+
try {
|
|
206
|
+
const layout = instances.map(i => ({
|
|
207
|
+
instanceId: i.instanceId,
|
|
208
|
+
widgetId: i.widgetId,
|
|
209
|
+
column: i.column,
|
|
210
|
+
order: i.order,
|
|
211
|
+
}));
|
|
212
|
+
localStorage.setItem('foxclaw_widget_layout', JSON.stringify(layout));
|
|
213
|
+
} catch {}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function loadLayout() {
|
|
217
|
+
try {
|
|
218
|
+
const saved = JSON.parse(localStorage.getItem('foxclaw_widget_layout'));
|
|
219
|
+
if (saved && saved.length) {
|
|
220
|
+
const valid = saved.filter(i => registry.has(i.widgetId));
|
|
221
|
+
if (valid.length) { setLayout(valid); return true; }
|
|
222
|
+
}
|
|
223
|
+
} catch {}
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function setEditMode(on) {
|
|
228
|
+
instances.forEach(inst => {
|
|
229
|
+
if (!inst._el) return;
|
|
230
|
+
const rm = inst._el.querySelector('.ph-remove');
|
|
231
|
+
if (rm) rm.style.display = on ? 'block' : 'none';
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function getLibrary() {
|
|
236
|
+
return [...registry.values()].map(spec => ({
|
|
237
|
+
id: spec.id,
|
|
238
|
+
title: spec.title,
|
|
239
|
+
icon: spec.icon,
|
|
240
|
+
defaultColumn: spec.defaultColumn,
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
register, init, setLayout, defaultLayout, renderAll,
|
|
246
|
+
dispatch, notifyAgentChange, refreshAll, setStatus,
|
|
247
|
+
addInstance, removeInstance, captureLayoutFromDOM,
|
|
248
|
+
saveLayout, loadLayout, setEditMode, getLibrary,
|
|
249
|
+
get instances() { return instances; },
|
|
250
|
+
get ctx() { return ctx; },
|
|
251
|
+
};
|
|
252
|
+
})();
|