foxclaw 0.1.2 → 0.1.4
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/index.js +1 -8
- package/package.json +1 -1
- package/python/.env.example +8 -0
- package/python/.github/workflows/ci.yml +47 -2
- package/python/.github/workflows/release.yml +5 -0
- package/python/CHANGELOG.md +100 -0
- package/python/CHANGELOG_CN.md +100 -0
- package/python/README.md +17 -2
- package/python/README_CN.md +38 -20
- package/python/bench/bm25_audit.py +1 -14
- package/python/bench/bm25_regression.py +0 -1
- package/python/bench/bm25_stress.py +0 -4
- package/python/bench/cd_audit.py +0 -23
- package/python/bench/chaos.py +6 -8
- package/python/bench/e2e_real_models.py +0 -1
- package/python/bench/llm_retry_test.py +2 -9
- package/python/bench/load_test.py +5 -8
- package/python/bench/vector_ivf_upgrade.py +1 -7
- package/python/docs/CONTENT_GUARD.md +189 -0
- package/python/docs/CONTENT_GUARD_CN.md +189 -0
- package/python/docs/RELEASE.md +78 -37
- package/python/docs/RUN_CN.md +2 -2
- package/python/evals/governance/cases.py +0 -37
- package/python/evals/governance/run_evals.py +5 -37
- package/python/examples/governance_middleware_demo.py +1 -6
- package/python/examples/langgraph_governance_demo.py +7 -11
- package/python/foxclaw/__init__.py +74 -152
- package/python/foxclaw/agents/base.py +82 -136
- package/python/foxclaw/agents/impl/_helpers.py +2 -10
- package/python/foxclaw/agents/impl/finance.py +4 -21
- package/python/foxclaw/agents/impl/office.py +7 -24
- package/python/foxclaw/agents/impl/supervisor.py +12 -79
- package/python/foxclaw/agents/mixins/_context.py +0 -23
- package/python/foxclaw/agents/mixins/augment.py +10 -16
- package/python/foxclaw/agents/mixins/llm.py +7 -6
- package/python/foxclaw/agents/mixins/memory.py +23 -3
- package/python/foxclaw/agents/mixins/preference.py +58 -8
- package/python/foxclaw/agents/mixins/prompt.py +59 -12
- package/python/foxclaw/agents/mixins/skillbox.py +6 -6
- package/python/foxclaw/agents/mixins/tool_exec.py +16 -42
- package/python/foxclaw/agents/rules/finance/RULES.md +131 -0
- package/python/foxclaw/api/__init__.py +18 -77
- package/python/foxclaw/api/_state.py +43 -0
- package/python/foxclaw/api/bootstrap.py +114 -0
- package/python/foxclaw/api/middleware.py +5 -28
- package/python/foxclaw/api/routes/ahs.py +60 -73
- package/python/foxclaw/api/routes/attachments.py +5 -6
- package/python/foxclaw/api/routes/browser.py +7 -11
- package/python/foxclaw/api/routes/domain.py +18 -26
- package/python/foxclaw/api/routes/knowledge.py +3 -21
- package/python/foxclaw/api/routes/llm_admin.py +21 -33
- package/python/foxclaw/api/routes/memory.py +50 -12
- package/python/foxclaw/api/routes/orchestration.py +3 -5
- package/python/foxclaw/api/routes/recovery.py +4 -3
- package/python/foxclaw/api/routes/review.py +2 -11
- package/python/foxclaw/api/routes/search.py +3 -7
- package/python/foxclaw/api/routes/system.py +33 -49
- package/python/foxclaw/api/routes/task.py +31 -49
- package/python/foxclaw/api/routes/ws.py +2 -6
- package/python/foxclaw/api/spine.py +1 -4
- package/python/foxclaw/behavior/__init__.py +20 -0
- package/python/foxclaw/behavior/behavior.yaml +62 -0
- package/python/foxclaw/behavior/spec.py +287 -0
- package/python/foxclaw/browser/action/action_executor.py +1 -5
- package/python/foxclaw/browser/action/action_types.py +0 -1
- package/python/foxclaw/browser/action/url_policy.py +1 -5
- package/python/foxclaw/browser/adapter/web_adapter.py +1 -1
- package/python/foxclaw/browser/driver/playwright_driver.py +20 -16
- package/python/foxclaw/browser/perception/dom_extractor.py +0 -1
- package/python/foxclaw/browser/perception/element_indexer.py +1 -2
- package/python/foxclaw/browser/service.py +7 -11
- package/python/foxclaw/capability/embedding_service.py +4 -6
- package/python/foxclaw/channels/__init__.py +9 -11
- package/python/foxclaw/channels/discord.py +4 -13
- package/python/foxclaw/channels/dispatcher.py +2 -27
- package/python/foxclaw/channels/feishu.py +10 -20
- package/python/foxclaw/channels/openclaw_bridge.py +4 -9
- package/python/foxclaw/channels/signing.py +9 -9
- package/python/foxclaw/channels/telegram.py +3 -4
- package/python/foxclaw/channels/weixin.py +7 -17
- package/python/foxclaw/cli.py +42 -13
- package/python/foxclaw/cognitive/reasoner.py +9 -10
- package/python/foxclaw/cognitive/state.py +18 -24
- package/python/foxclaw/core/audit_chain.py +1 -3
- package/python/foxclaw/core/audit_sink.py +3 -3
- package/python/foxclaw/core/compaction.py +8 -26
- package/python/foxclaw/core/config.py +2 -2
- package/python/foxclaw/core/confirm_nonce.py +6 -12
- package/python/foxclaw/core/content_guard.py +341 -0
- package/python/foxclaw/core/envfile.py +2 -2
- package/python/foxclaw/core/failure_policy.py +17 -26
- package/python/foxclaw/core/gateway.py +6 -10
- package/python/foxclaw/core/governance_audit.py +3 -7
- package/python/foxclaw/core/idempotency.py +15 -22
- package/python/foxclaw/core/injection_guard.py +10 -29
- package/python/foxclaw/core/memory_adapter.py +53 -60
- package/python/foxclaw/core/metrics.py +4 -5
- package/python/foxclaw/core/model_router.py +74 -150
- package/python/foxclaw/core/paths.py +1 -1
- package/python/foxclaw/core/recovery.py +21 -34
- package/python/foxclaw/core/scheduler.py +23 -26
- package/python/foxclaw/core/secrets.py +0 -3
- package/python/foxclaw/core/sensitive_write.py +283 -0
- package/python/foxclaw/core/sessions.py +4 -6
- package/python/foxclaw/core/settings.py +16 -32
- package/python/foxclaw/core/shared_write.py +11 -23
- package/python/foxclaw/core/steering_queue.py +12 -11
- package/python/foxclaw/core/system_bus.py +1 -1
- package/python/foxclaw/core/thought_chain.py +30 -32
- package/python/foxclaw/core/token_meter.py +9 -13
- package/python/foxclaw/core/tools.py +4 -12
- package/python/foxclaw/core/tracing.py +25 -40
- package/python/foxclaw/core/truth_pipeline.py +5 -9
- package/python/foxclaw/core/update_check.py +149 -0
- package/python/foxclaw/core/vec_recall_adapter.py +11 -37
- package/python/foxclaw/core/verify.py +6 -14
- package/python/foxclaw/core/web_search.py +4 -28
- package/python/foxclaw/finance/evidence.py +14 -18
- package/python/foxclaw/finance/fx.py +1 -3
- package/python/foxclaw/finance/graph.py +9 -18
- package/python/foxclaw/finance/models.py +20 -24
- package/python/foxclaw/finance/nlparse.py +12 -72
- package/python/foxclaw/finance/policy.py +8 -36
- package/python/foxclaw/finance/reasoner.py +3 -11
- package/python/foxclaw/finance/reasoning.py +13 -34
- package/python/foxclaw/finance/reconcile.py +5 -10
- package/python/foxclaw/finance/runtime.py +19 -46
- package/python/foxclaw/governance/middleware.py +13 -21
- package/python/foxclaw/harness/_base.py +2 -8
- package/python/foxclaw/harness/_policy.py +19 -38
- package/python/foxclaw/harness/drift.py +1 -13
- package/python/foxclaw/harness/event_bus.py +2 -5
- package/python/foxclaw/harness/harness.py +9 -97
- package/python/foxclaw/harness/loop_detection.py +11 -18
- package/python/foxclaw/itinerary/amap_client.py +2 -5
- package/python/foxclaw/itinerary/models.py +7 -7
- package/python/foxclaw/itinerary/reasoner.py +1 -6
- package/python/foxclaw/itinerary/reasoning.py +15 -21
- package/python/foxclaw/itinerary/runtime.py +8 -12
- package/python/foxclaw/kernel/capabilities.py +5 -6
- package/python/foxclaw/kernel/policy_gate.py +4 -10
- package/python/foxclaw/kernel/process_manager.py +17 -36
- package/python/foxclaw/kernel/scheduler.py +3 -9
- package/python/foxclaw/kernel/sentinel.py +13 -23
- package/python/foxclaw/kernel/sentinel_client.py +12 -15
- package/python/foxclaw/kernel/spine.py +9 -9
- package/python/foxclaw/knowledge/__init__.py +4 -20
- package/python/foxclaw/knowledge/truth_crystallizer.py +5 -8
- package/python/foxclaw/learning/knowledge_graph.py +4 -9
- package/python/foxclaw/learning/models.py +13 -13
- package/python/foxclaw/learning/reasoner.py +1 -4
- package/python/foxclaw/learning/runtime.py +19 -31
- package/python/foxclaw/learning/spaced_repetition.py +2 -7
- package/python/foxclaw/mcp_server.py +2 -3
- package/python/foxclaw/orchestration/__init__.py +16 -33
- package/python/foxclaw/pipeline/cognitive_pipeline.py +45 -97
- package/python/foxclaw/pipeline/stage_meta.py +21 -0
- package/python/foxclaw/pipeline/supervisor_stages.py +13 -42
- package/python/foxclaw/planning/llm_planner.py +3 -3
- package/python/foxclaw/planning/planner.py +6 -11
- package/python/foxclaw/search/agent_port.py +7 -11
- package/python/foxclaw/search/evidence.py +0 -4
- package/python/foxclaw/search/internal_search.py +3 -5
- package/python/foxclaw/search/models.py +11 -13
- package/python/foxclaw/search/planner.py +3 -3
- package/python/foxclaw/search/retriever.py +1 -1
- package/python/foxclaw/search/runtime.py +1 -8
- package/python/foxclaw/skills/__init__.py +46 -100
- package/python/foxclaw/skills/archive.py +111 -0
- package/python/foxclaw/skills/fetch.py +226 -0
- package/python/foxclaw/skills/hooks_spec.py +21 -25
- package/python/foxclaw/skills/install_cmd.py +216 -0
- package/python/foxclaw/skills/lifecycle.py +16 -42
- package/python/foxclaw/skills/markdown_skill.py +10 -9
- package/python/foxclaw/skills/mcp_client.py +5 -11
- package/python/foxclaw/skills/mcp_store.py +0 -3
- package/python/foxclaw/skills/permission.py +13 -48
- package/python/foxclaw/skills/pipeline.py +21 -53
- package/python/foxclaw/skills/policy.py +4 -10
- package/python/foxclaw/skills/review.py +3 -3
- package/python/frontend/deck/auth.js +0 -7
- package/python/frontend/deck/chat_model_picker.js +0 -54
- package/python/frontend/deck/domain.js +0 -20
- package/python/frontend/deck/main.js +0 -144
- package/python/frontend/deck/markdown.js +0 -4
- package/python/frontend/deck/settings.js +1 -18
- package/python/frontend/deck/state.js +0 -1
- package/python/frontend/deck/util.js +0 -2
- package/python/frontend/deck/visuals.js +0 -22
- package/python/frontend/planet/planet.js +18 -201
- package/python/frontend/v3/assets/index-JKfHlb-a.css +1 -0
- package/python/frontend/v3/assets/index-tN90dpUH.js +34 -0
- package/python/frontend/v3/index.html +3 -3
- package/python/frontend/widget_runtime.js +0 -43
- package/python/frontend/widgets.js +0 -57
- package/python/frontend_src/index.html +1 -1
- package/python/frontend_src/package-lock.json +2 -2
- package/python/frontend_src/package.json +1 -1
- package/python/frontend_src/src/App.vue +3 -7
- package/python/frontend_src/src/api.js +0 -7
- package/python/frontend_src/src/components/ChatDock.vue +27 -39
- package/python/frontend_src/src/components/DocViewer.vue +0 -9
- package/python/frontend_src/src/components/Inspector.vue +0 -6
- package/python/frontend_src/src/components/LeftRail.vue +60 -39
- package/python/frontend_src/src/components/MenuPopover.vue +9 -11
- package/python/frontend_src/src/components/MessageStream.vue +18 -30
- package/python/frontend_src/src/components/ModelPicker.vue +0 -5
- package/python/frontend_src/src/components/QuickIngest.vue +0 -6
- package/python/frontend_src/src/components/Stage.vue +71 -25
- package/python/frontend_src/src/components/ToolMenu.vue +0 -3
- package/python/frontend_src/src/components/TopBar.vue +38 -10
- package/python/frontend_src/src/components/panels/ActivityPanel.vue +0 -2
- package/python/frontend_src/src/components/panels/AgentsPanel.vue +2 -5
- package/python/frontend_src/src/components/panels/KnowledgePanel.vue +0 -16
- package/python/frontend_src/src/components/panels/MemoryPanel.vue +42 -3
- package/python/frontend_src/src/components/panels/PanelBox.vue +6 -7
- package/python/frontend_src/src/components/panels/ReviewPanel.vue +0 -16
- package/python/frontend_src/src/components/panels/SettingsPanel.vue +142 -38
- package/python/frontend_src/src/components/panels/TasksPanel.vue +0 -1
- package/python/frontend_src/src/components/panels/ToolsPanel.vue +125 -19
- package/python/frontend_src/src/lib/fmt.js +0 -4
- 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 +0 -14
- package/python/frontend_src/src/main.js +2 -0
- package/python/frontend_src/src/stores/app.js +17 -32
- package/python/frontend_src/src/stores/chat.js +0 -34
- package/python/frontend_src/src/stores/model.js +0 -8
- package/python/frontend_src/src/stores/panels.js +16 -44
- package/python/frontend_src/src/stores/profile.js +31 -0
- package/python/frontend_src/src/stores/system.js +25 -0
- package/python/frontend_src/vite.config.js +0 -7
- package/python/pyproject.toml +17 -3
- package/python/requirements.txt +311 -0
- package/python/tests/conftest.py +0 -22
- package/python/tests/run_all.py +4 -66
- package/python/tests/test_agent_lifecycle.py +4 -38
- package/python/tests/test_agent_rules.py +81 -0
- package/python/tests/test_ahs_p2.py +4 -25
- package/python/tests/test_anthropic_tools.py +1 -15
- package/python/tests/test_api.py +19 -9
- package/python/tests/test_api_auth.py +1 -5
- package/python/tests/test_attachments.py +9 -25
- package/python/tests/test_audit_chain.py +2 -7
- package/python/tests/test_audit_sink.py +0 -6
- package/python/tests/test_behavior_spec.py +198 -0
- package/python/tests/test_browser.py +2 -6
- package/python/tests/test_browser_request_guard.py +0 -4
- package/python/tests/test_capabilities.py +0 -6
- package/python/tests/test_channel_signing.py +2 -9
- package/python/tests/test_channels.py +1 -11
- package/python/tests/test_config_layering.py +0 -4
- package/python/tests/test_confirm_nonce.py +1 -12
- package/python/tests/test_conflict_dismiss.py +143 -0
- package/python/tests/test_content_guard.py +177 -0
- package/python/tests/test_context_compaction_wiring.py +1 -7
- package/python/tests/test_dispatch.py +0 -6
- package/python/tests/test_domain_evals.py +11 -80
- package/python/tests/test_domain_import.py +0 -6
- package/python/tests/test_domain_reasoners.py +0 -14
- package/python/tests/test_e2e.py +0 -17
- package/python/tests/test_emb_cache.py +7 -17
- package/python/tests/test_embedding_singleton.py +1 -3
- package/python/tests/test_evals_smoke.py +0 -24
- package/python/tests/test_event_spine.py +10 -18
- package/python/tests/test_evidence_semantic.py +1 -14
- package/python/tests/test_evidence_sse.py +3 -6
- package/python/tests/test_file_ingest.py +0 -11
- package/python/tests/test_finance.py +0 -9
- package/python/tests/test_finance_ledger.py +5 -12
- package/python/tests/test_finance_persist.py +8 -12
- package/python/tests/test_gateway.py +3 -22
- package/python/tests/test_governance.py +5 -52
- package/python/tests/test_governance_audit.py +4 -39
- package/python/tests/test_governance_middleware.py +1 -7
- package/python/tests/test_hkc.py +6 -24
- package/python/tests/test_hkc_index_build_manager.py +0 -33
- package/python/tests/test_hkc_manifest_reuse.py +4 -27
- package/python/tests/test_hkc_search_event_sync.py +3 -54
- package/python/tests/test_import_path_guard.py +0 -6
- package/python/tests/test_injection_guard.py +18 -36
- package/python/tests/test_integration.py +5 -29
- package/python/tests/test_itinerary.py +0 -3
- package/python/tests/test_kee_semantic.py +0 -5
- package/python/tests/test_kernel.py +1 -11
- package/python/tests/test_learning.py +3 -12
- package/python/tests/test_llm_admin.py +4 -19
- package/python/tests/test_llm_planner.py +1 -23
- package/python/tests/test_markdown_skills.py +3 -14
- package/python/tests/test_markdown_skills_openclaw.py +4 -9
- package/python/tests/test_mcp_connectors.py +3 -15
- package/python/tests/test_mcp_guardian_discovery.py +2 -6
- package/python/tests/test_mcp_no_memory.py +3 -3
- package/python/tests/test_mcp_policy_gate.py +0 -1
- package/python/tests/test_mcp_server.py +6 -9
- package/python/tests/test_memory_recall.py +1 -4
- package/python/tests/test_metrics.py +0 -8
- package/python/tests/test_multi_chain.py +1 -13
- package/python/tests/test_multimodal.py +5 -18
- package/python/tests/test_negotiation.py +3 -13
- package/python/tests/test_orchestration.py +1 -11
- package/python/tests/test_orchestration_decoupled.py +0 -6
- package/python/tests/test_p3_p5_hardening.py +3 -17
- package/python/tests/test_parallel_dispatch.py +4 -12
- package/python/tests/test_pipeline.py +17 -58
- package/python/tests/test_plan_visible.py +4 -4
- package/python/tests/test_planner.py +0 -7
- package/python/tests/test_policy_gate.py +2 -3
- package/python/tests/test_profile.py +67 -0
- package/python/tests/test_readme_claims.py +163 -0
- package/python/tests/test_reasoner.py +2 -17
- package/python/tests/test_release_check.py +2 -13
- package/python/tests/test_resume_checkpoint.py +7 -15
- package/python/tests/test_routing.py +2 -12
- package/python/tests/test_scheduler.py +7 -10
- package/python/tests/test_search.py +1 -11
- package/python/tests/test_secrets.py +4 -10
- package/python/tests/test_semantic.py +1 -10
- package/python/tests/test_sensitive_write.py +181 -0
- package/python/tests/test_sessions.py +3 -4
- package/python/tests/test_settings.py +2 -18
- package/python/tests/test_shadow_learning.py +3 -43
- package/python/tests/test_shared_write.py +0 -7
- package/python/tests/test_skill_taint_gate.py +1 -10
- package/python/tests/test_skills.py +2 -18
- package/python/tests/test_skills_fetch.py +282 -0
- package/python/tests/test_stats_and_events.py +2 -5
- package/python/tests/test_streaming.py +2 -7
- package/python/tests/test_supervisor_pipeline.py +4 -5
- package/python/tests/test_supervisor_triage.py +4 -10
- package/python/tests/test_taint.py +2 -7
- package/python/tests/test_task_stream.py +1 -12
- package/python/tests/test_thinking_sse.py +0 -1
- package/python/tests/test_tool_center.py +1 -17
- package/python/tests/test_tool_parallel.py +2 -2
- package/python/tests/test_tool_params.py +1 -5
- package/python/tests/test_tool_use.py +0 -13
- package/python/tests/test_toplevel_concurrency.py +3 -4
- package/python/tests/test_tracing.py +7 -41
- package/python/tests/test_truth_crystallizer.py +4 -6
- package/python/tests/test_truth_flow.py +2 -7
- package/python/tests/test_update_check.py +95 -0
- package/python/tests/test_verify_evidence.py +8 -21
- package/python/tests/test_version_sync.py +35 -6
- package/python/tests/test_web_trigger.py +0 -17
- package/python/tools/build_content_lexicon.py +218 -0
- package/python/tools/bundle_web.py +98 -0
- package/python/tools/check_faiss_type.py +0 -1
- package/python/tools/check_log.ps1 +0 -8
- package/python/tools/mypy_baseline.txt +12 -4
- package/python/tools/mypy_ratchet.py +52 -6
- package/python/tools/pack.py +0 -5
- package/python/tools/recheck_conflicts.py +156 -0
- package/python/tools/release_check.py +24 -15
- package/python/tools/restart_foxclaw.ps1 +5 -8
- package/python/tools/shared_write_audit.py +1 -15
- package/python/tools/size_check.py +1 -1
- package/python/tools/strip_comments.py +228 -0
- package/python/vendor/hkc/hkc_api/routes/ability.py +31 -0
- package/python/vendor/hkc/hkc_api/schemas.py +11 -0
- package/python/vendor/hkc/hkc_kee/kee.py +124 -3
- package/python/vendor/hkc/hkc_sdk/base.py +22 -0
- package/python/vendor/hkc/hkc_sdk/direct_client.py +10 -0
- package/python/vendor/hkc/hkc_sdk/http_client.py +19 -0
- package/python/foxclaw/api/app.py +0 -123
- package/python/frontend/v3/assets/index-BD7VPbMV.js +0 -33
- package/python/frontend/v3/assets/index-CAvnYWGH.css +0 -1
|
@@ -44,9 +44,6 @@ async function flip(s) {
|
|
|
44
44
|
busy.value = ''
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/* ── 单技能测试:POST /ahs/skills/{id}/test ──
|
|
48
|
-
走真管线(权限/断路器/SSRF),所以界面要能填参数,也要把 needs_confirmation /
|
|
49
|
-
blocked / circuit_open 这些非成功态原样显示,不能只画个绿勾。 */
|
|
50
47
|
const tId = ref('')
|
|
51
48
|
const tArgs = ref({})
|
|
52
49
|
const tBusy = ref(false)
|
|
@@ -74,7 +71,6 @@ function beginTest(s) {
|
|
|
74
71
|
err.value = ''
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
/* params 是 {名: 类型} 的朴素 schema,类型只是提示;这里按声明做最小转换,其余原样送字符串 */
|
|
78
74
|
function coerce(params, args) {
|
|
79
75
|
const out = {}
|
|
80
76
|
for (const [k, ty] of Object.entries(params || {})) {
|
|
@@ -133,7 +129,6 @@ async function dropSkill(s) {
|
|
|
133
129
|
|
|
134
130
|
const splitList = (t) => String(t || '').split(/[,,\s]+/).map((s) => s.trim()).filter(Boolean)
|
|
135
131
|
|
|
136
|
-
/* "city:str, days:int" → {city:"str", days:"int"} */
|
|
137
132
|
function parseParams(txt) {
|
|
138
133
|
const out = {}
|
|
139
134
|
for (const part of String(txt || '').split(/[,,;\n]/)) {
|
|
@@ -145,7 +140,6 @@ function parseParams(txt) {
|
|
|
145
140
|
return out
|
|
146
141
|
}
|
|
147
142
|
|
|
148
|
-
/* "Authorization: Bearer x" 每行一条 → dict(空行 / 无冒号行忽略) */
|
|
149
143
|
function parseHeaders(txt) {
|
|
150
144
|
const out = {}
|
|
151
145
|
for (const line of String(txt || '').split('\n')) {
|
|
@@ -155,8 +149,6 @@ function parseHeaders(txt) {
|
|
|
155
149
|
return out
|
|
156
150
|
}
|
|
157
151
|
|
|
158
|
-
/* ── 安装技能:POST /ahs/skills ──
|
|
159
|
-
后端只收 web_api / mcp;审核门 deny → 403, warn → 409 needs_ack(要再点一次「已知风险」) */
|
|
160
152
|
const SIDE = { read: 'read · 只读', write: 'write · 写入', send: 'send · 代发', pay: 'pay · 付款' }
|
|
161
153
|
const showIns = ref(false)
|
|
162
154
|
const insBusy = ref(false)
|
|
@@ -220,8 +212,93 @@ async function doInstall(ack = false) {
|
|
|
220
212
|
}
|
|
221
213
|
}
|
|
222
214
|
|
|
223
|
-
|
|
224
|
-
|
|
215
|
+
const MI_MAX = 4 * 1024 * 1024
|
|
216
|
+
const miOpen = ref(false)
|
|
217
|
+
const miBusy = ref(false)
|
|
218
|
+
const miErr = ref('')
|
|
219
|
+
const miOk = ref('')
|
|
220
|
+
const miAck = ref(false)
|
|
221
|
+
const miText = ref('')
|
|
222
|
+
const miFile = ref('')
|
|
223
|
+
const miB64 = ref('') // zip 的 base64;非空时优先于 miText
|
|
224
|
+
const miRef = ref(null)
|
|
225
|
+
|
|
226
|
+
function toggleMi() {
|
|
227
|
+
miOpen.value = !miOpen.value
|
|
228
|
+
miErr.value = ''
|
|
229
|
+
miOk.value = ''
|
|
230
|
+
miAck.value = false
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function resetMi() {
|
|
234
|
+
miText.value = ''
|
|
235
|
+
miFile.value = ''
|
|
236
|
+
miB64.value = ''
|
|
237
|
+
miAck.value = false
|
|
238
|
+
if (miRef.value) miRef.value.value = ''
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function toB64(file) {
|
|
242
|
+
return new Promise((resolve, reject) => {
|
|
243
|
+
const fr = new FileReader()
|
|
244
|
+
fr.onload = () => {
|
|
245
|
+
const s = String(fr.result || '')
|
|
246
|
+
resolve(s.slice(s.indexOf(',') + 1)) // 去掉 data:...;base64, 前缀
|
|
247
|
+
}
|
|
248
|
+
fr.onerror = () => reject(new Error('读取文件失败'))
|
|
249
|
+
fr.readAsDataURL(file)
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function onMiFile(ev) {
|
|
254
|
+
const f = ev.target.files && ev.target.files[0]
|
|
255
|
+
miFile.value = ''
|
|
256
|
+
miB64.value = ''
|
|
257
|
+
miErr.value = ''
|
|
258
|
+
miOk.value = ''
|
|
259
|
+
miAck.value = false
|
|
260
|
+
if (!f) return
|
|
261
|
+
miFile.value = `${f.name} · ${(f.size / 1024).toFixed(0)} KB`
|
|
262
|
+
if (f.size > MI_MAX) { miErr.value = '文件超过 4MB,拒绝上传'; return }
|
|
263
|
+
try {
|
|
264
|
+
if (/\.zip$/i.test(f.name)) {
|
|
265
|
+
miB64.value = await toB64(f)
|
|
266
|
+
miText.value = ''
|
|
267
|
+
} else {
|
|
268
|
+
miText.value = await f.text()
|
|
269
|
+
}
|
|
270
|
+
} catch (e) {
|
|
271
|
+
miErr.value = String(e.message || e)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function doMdInstall(ack = false) {
|
|
276
|
+
if (miBusy.value) return
|
|
277
|
+
const content = miText.value.trim()
|
|
278
|
+
if (!ack && !content && !miB64.value) {
|
|
279
|
+
miErr.value = '粘贴 SKILL.md 正文,或选一个 .md / .zip 文件'
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
miBusy.value = true
|
|
283
|
+
miErr.value = ''
|
|
284
|
+
miOk.value = ''
|
|
285
|
+
const body = { acknowledged: ack }
|
|
286
|
+
if (miB64.value) body.package_b64 = miB64.value
|
|
287
|
+
else body.content = content
|
|
288
|
+
try {
|
|
289
|
+
const d = await postJSON('/ahs/md-skills', body)
|
|
290
|
+
const name = (d.skill && (d.skill.name || d.skill.id)) || '指令技能'
|
|
291
|
+
miOk.value = `${d.created ? '已安装' : '已更新'}「${name}」`
|
|
292
|
+
resetMi()
|
|
293
|
+
await refreshPanel('tools')
|
|
294
|
+
} catch (e) {
|
|
295
|
+
miErr.value = String(e.message || e)
|
|
296
|
+
miAck.value = !!(e.detail && e.detail.needs_ack)
|
|
297
|
+
} finally {
|
|
298
|
+
miBusy.value = false
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
225
302
|
const showMcpAdd = ref(false)
|
|
226
303
|
const mcpBusy = ref(false)
|
|
227
304
|
const mcpErr = ref('')
|
|
@@ -265,7 +342,6 @@ async function addMcp(ack = false) {
|
|
|
265
342
|
}
|
|
266
343
|
}
|
|
267
344
|
|
|
268
|
-
/* 重连:server 那边的工具会变,POST .../refresh 增量对齐注册表 */
|
|
269
345
|
async function refreshMcp(s) {
|
|
270
346
|
if (mcpBusy.value) return
|
|
271
347
|
mcpBusy.value = true
|
|
@@ -392,6 +468,43 @@ async function delMcp(s) {
|
|
|
392
468
|
</div>
|
|
393
469
|
</div>
|
|
394
470
|
|
|
471
|
+
<div class="pn-sec">
|
|
472
|
+
<div class="pn-h">
|
|
473
|
+
安装指令技能
|
|
474
|
+
<button class="mbtn" @click="toggleMi">{{ miOpen ? '收起' : '+ 上传' }}</button>
|
|
475
|
+
</div>
|
|
476
|
+
<div v-if="miOpen" class="tk-form">
|
|
477
|
+
<label class="f"><span>SKILL.md 或 OpenClaw 包(.md / .zip)</span>
|
|
478
|
+
<input ref="miRef" type="file" accept=".md,.markdown,.zip" @change="onMiFile" />
|
|
479
|
+
</label>
|
|
480
|
+
<div v-if="miFile" class="pn-note">{{ miFile }}</div>
|
|
481
|
+
<label class="f"><span>或粘贴正文(frontmatter + 指示)</span>
|
|
482
|
+
<textarea
|
|
483
|
+
v-model="miText"
|
|
484
|
+
rows="8"
|
|
485
|
+
spellcheck="false"
|
|
486
|
+
:disabled="!!miB64"
|
|
487
|
+
placeholder="--- name: my-skill / description: 什么时候用它 --- 然后写正文"
|
|
488
|
+
/>
|
|
489
|
+
</label>
|
|
490
|
+
<div class="fbar">
|
|
491
|
+
<button class="go" :disabled="miBusy" @click="doMdInstall(false)">
|
|
492
|
+
{{ miBusy ? '安装中…' : '安装' }}
|
|
493
|
+
</button>
|
|
494
|
+
<button v-if="miAck" class="go warn" :disabled="miBusy" @click="doMdInstall(true)">
|
|
495
|
+
已知风险,继续安装
|
|
496
|
+
</button>
|
|
497
|
+
<span v-if="miErr" class="tip bad">{{ miErr }}</span>
|
|
498
|
+
<span v-else-if="miOk" class="tip ok">{{ miOk }}</span>
|
|
499
|
+
<span v-else class="tip dim">只取 SKILL.md 与 _meta.json;包内 scripts/ 不落地、不执行</span>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
<div v-else class="pn-note">
|
|
503
|
+
指令技能是注入提示词的 markdown,不是可执行工具。命令行也能装:
|
|
504
|
+
<code>foxclaw skills install @owner/slug</code>、<code>github:owner/repo</code>、<code>./pkg.zip</code>。
|
|
505
|
+
</div>
|
|
506
|
+
</div>
|
|
507
|
+
|
|
395
508
|
<div class="pn-sec">
|
|
396
509
|
<div class="pn-h">
|
|
397
510
|
安装技能
|
|
@@ -532,11 +645,6 @@ async function delMcp(s) {
|
|
|
532
645
|
<button class="mbtn danger" @click="delMcp(s)">移除</button>
|
|
533
646
|
</div>
|
|
534
647
|
</div>
|
|
535
|
-
|
|
536
|
-
<div class="pn-note">
|
|
537
|
-
指令技能正文 <code>/api/ahs/md-skills/{id}</code>,执行技能运行 <code>POST /api/ahs/skills/{id}/test</code>;
|
|
538
|
-
连接器与技能面板是同一份数据(<code>/api/ahs/mcp/servers</code>)。
|
|
539
|
-
</div>
|
|
540
648
|
</PanelBox>
|
|
541
649
|
</template>
|
|
542
650
|
|
|
@@ -550,7 +658,6 @@ async function delMcp(s) {
|
|
|
550
658
|
.sw.on { background: rgba(26, 157, 95, 0.12); color: var(--green); }
|
|
551
659
|
.sw:disabled { opacity: 0.5; }
|
|
552
660
|
|
|
553
|
-
/* 行内小按钮:测试 / 删除 / 新增 —— 原来「执行技能」整行是死的,点了没反应 */
|
|
554
661
|
.mbtn {
|
|
555
662
|
flex-shrink: 0; padding: 4px 10px; border-radius: var(--r-pill);
|
|
556
663
|
font-size: 11px; font-family: var(--mono); color: var(--dim);
|
|
@@ -562,7 +669,6 @@ async function delMcp(s) {
|
|
|
562
669
|
.mbtn.danger:hover { color: var(--red); border-color: rgba(229, 72, 77, 0.35); }
|
|
563
670
|
.mbtn:disabled { opacity: 0.5; }
|
|
564
671
|
|
|
565
|
-
/* ── 表单(安装技能 / 接入连接器 / 技能测试)── */
|
|
566
672
|
.tk-form, .tk-test {
|
|
567
673
|
margin: 4px 0 6px;
|
|
568
674
|
padding: 11px 12px;
|
|
@@ -595,6 +701,7 @@ async function delMcp(s) {
|
|
|
595
701
|
.f textarea { resize: vertical; line-height: 1.6; }
|
|
596
702
|
.f input:focus, .f select:focus, .f textarea:focus { border-color: var(--line); background: #fff; }
|
|
597
703
|
.f input::placeholder, .f textarea::placeholder { color: var(--dim); }
|
|
704
|
+
.f input[type='file'] { padding: 4px 6px; font-size: 11.5px; color: var(--dim); }
|
|
598
705
|
|
|
599
706
|
.chk {
|
|
600
707
|
display: flex; align-items: center; gap: 6px;
|
|
@@ -622,7 +729,6 @@ async function delMcp(s) {
|
|
|
622
729
|
.tip.ok { color: var(--green); }
|
|
623
730
|
.tip.bad { color: var(--red); white-space: normal; }
|
|
624
731
|
|
|
625
|
-
/* 测试结果:成功/失败都原文展示,失败(needs_confirmation/blocked)不涂成成功色 */
|
|
626
732
|
.tk-res {
|
|
627
733
|
margin-top: 4px; padding: 8px 10px; border-radius: var(--r-sm);
|
|
628
734
|
background: rgba(23, 32, 26, 0.03); border: 1px solid var(--line-soft);
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
/* 7 个面板共用的时间/数字格式化。集中一份,避免每个组件各写一遍还写得不一样。 */
|
|
2
1
|
|
|
3
|
-
/* 后端时间戳三种形态都有:秒 float(事件总线)、毫秒 int、ISO 字符串(记忆 created_at)。
|
|
4
|
-
字符串交给 Date 自己解析,数字按量级判断。 */
|
|
5
2
|
function toDate(ts) {
|
|
6
3
|
if (!ts) return null
|
|
7
4
|
if (typeof ts === 'string') {
|
|
@@ -41,7 +38,6 @@ export function fmtMs(ms) {
|
|
|
41
38
|
return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${Math.round(ms)}ms`
|
|
42
39
|
}
|
|
43
40
|
|
|
44
|
-
/* 截断到 n 个字符(中文按 1 计),用于行内摘要 */
|
|
45
41
|
export function clip(s, n = 46) {
|
|
46
42
|
const t = String(s ?? '').replace(/\s+/g, ' ').trim()
|
|
47
43
|
return t.length > n ? t.slice(0, n) + '…' : t
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { reactive } from 'vue'
|
|
2
|
+
import zh from './locales/zh.js'
|
|
3
|
+
import en from './locales/en.js'
|
|
4
|
+
|
|
5
|
+
const DICTS = { zh, en }
|
|
6
|
+
const STORE_KEY = 'foxclawLang'
|
|
7
|
+
|
|
8
|
+
export const LOCALES = [
|
|
9
|
+
{ id: 'zh', label: '中文', tag: 'Chinese', htmlLang: 'zh-CN', locale: 'zh-CN' },
|
|
10
|
+
{ id: 'en', label: 'English', tag: 'English', htmlLang: 'en', locale: 'en-US' },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
const stored = (() => {
|
|
14
|
+
try {
|
|
15
|
+
return localStorage.getItem(STORE_KEY)
|
|
16
|
+
} catch {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
})()
|
|
20
|
+
|
|
21
|
+
export const i18n = reactive({ locale: DICTS[stored] ? stored : 'zh' })
|
|
22
|
+
|
|
23
|
+
export const currentLocale = () => LOCALES.find((l) => l.id === i18n.locale) || LOCALES[0]
|
|
24
|
+
|
|
25
|
+
/** 数字/日期格式化用的 BCP-47 标签,跟随界面语言 */
|
|
26
|
+
export const numberLocale = () => currentLocale().locale
|
|
27
|
+
|
|
28
|
+
export function applyLangTag() {
|
|
29
|
+
document.documentElement.lang = currentLocale().htmlLang
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function setLocale(id) {
|
|
33
|
+
if (!DICTS[id] || id === i18n.locale) return
|
|
34
|
+
i18n.locale = id
|
|
35
|
+
try {
|
|
36
|
+
localStorage.setItem(STORE_KEY, id)
|
|
37
|
+
} catch {
|
|
38
|
+
/* 隐私模式下写不进去,不影响本次会话 */
|
|
39
|
+
}
|
|
40
|
+
applyLangTag()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** 取文案。读 i18n.locale 使其在模板中被 Vue 追踪,切换语言即时生效。 */
|
|
44
|
+
export function t(key, vars) {
|
|
45
|
+
const dict = DICTS[i18n.locale] || DICTS.zh
|
|
46
|
+
let s = dict[key]
|
|
47
|
+
if (s === undefined) s = DICTS.zh[key]
|
|
48
|
+
if (s === undefined) return key
|
|
49
|
+
if (vars) {
|
|
50
|
+
for (const k of Object.keys(vars)) s = s.split(`{${k}}`).join(String(vars[k]))
|
|
51
|
+
}
|
|
52
|
+
return s
|
|
53
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
'nav.overview': 'Overview',
|
|
3
|
+
'nav.activity': 'Activity',
|
|
4
|
+
'nav.tasks': 'Scheduled',
|
|
5
|
+
'nav.agents': 'Agents',
|
|
6
|
+
'nav.tools': 'Skills · Connectors',
|
|
7
|
+
'nav.usage': 'Usage',
|
|
8
|
+
'nav.knowledge': 'Library',
|
|
9
|
+
'nav.review': 'Review',
|
|
10
|
+
'nav.memory': 'Memory',
|
|
11
|
+
'nav.settings': 'Settings',
|
|
12
|
+
|
|
13
|
+
'group.workspace': 'Workspace',
|
|
14
|
+
'group.capability': 'Capability',
|
|
15
|
+
'group.knowledge': 'Knowledge',
|
|
16
|
+
'group.system': 'System',
|
|
17
|
+
|
|
18
|
+
'common.refresh': 'Refresh',
|
|
19
|
+
'common.loading': 'Loading…',
|
|
20
|
+
'common.offline': 'Backend offline',
|
|
21
|
+
'common.offlinePanel': 'Backend offline — this panel cannot load data right now',
|
|
22
|
+
'common.online': 'Online',
|
|
23
|
+
'common.offlineShort': 'Offline',
|
|
24
|
+
'common.save': 'Save',
|
|
25
|
+
'common.notSet': 'Not set',
|
|
26
|
+
'common.count': '{n}',
|
|
27
|
+
|
|
28
|
+
'rail.newSession': 'Start a new session',
|
|
29
|
+
'rail.newSessionBtn': '+ New session',
|
|
30
|
+
'rail.more': 'More',
|
|
31
|
+
'menu.title': 'More features',
|
|
32
|
+
'menu.close': 'Close (Esc)',
|
|
33
|
+
'rail.otherFeatures': 'Other features',
|
|
34
|
+
'rail.history': 'Sessions',
|
|
35
|
+
'rail.empty': 'No sessions yet · send a message to start',
|
|
36
|
+
'rail.untitled': 'New session',
|
|
37
|
+
'rail.rename': 'Rename session',
|
|
38
|
+
'rail.delete': 'Delete session',
|
|
39
|
+
'rail.sessionTitle': 'Session title',
|
|
40
|
+
'rail.open': 'Open {label}',
|
|
41
|
+
'rail.deleteConfirm': 'Delete session "{name}"?\nIts conversation history will be removed permanently.',
|
|
42
|
+
|
|
43
|
+
'app.expandInspector': 'Expand inspector',
|
|
44
|
+
'app.inspector': 'Inspect',
|
|
45
|
+
|
|
46
|
+
'topbar.systemStatus': 'Status',
|
|
47
|
+
'topbar.newVersion': 'Version {latest} available (current {current}) — open settings',
|
|
48
|
+
'topbar.planet': 'Open HKC Knowledge Planet',
|
|
49
|
+
'topbar.planetBtn': '🌐 Planet',
|
|
50
|
+
'topbar.settings': 'Settings (Ctrl+,)',
|
|
51
|
+
|
|
52
|
+
'settings.title': 'Settings',
|
|
53
|
+
'settings.tag': 'Settings',
|
|
54
|
+
'settings.groupModel': 'Model',
|
|
55
|
+
'settings.modelProvider': 'Model & provider',
|
|
56
|
+
'settings.modelProviderSub': 'Takes effect server-side immediately, no restart',
|
|
57
|
+
'settings.current': 'Active',
|
|
58
|
+
'settings.unconfigured': 'No key',
|
|
59
|
+
'settings.providerNote': '“No key” means the backend has no credential for that vendor. Custom model keys and base URLs go in the model capsule left of the composer.',
|
|
60
|
+
'settings.usage': 'Usage',
|
|
61
|
+
'settings.usageSub': 'Tokens, calls, balance',
|
|
62
|
+
'settings.groupChat': 'Chat',
|
|
63
|
+
'settings.mode': 'Mode',
|
|
64
|
+
'settings.modeSub': 'Token-by-token streaming / plan first, then execute',
|
|
65
|
+
'settings.stream': 'Stream',
|
|
66
|
+
'settings.orchestrate': 'Orchestrate',
|
|
67
|
+
'settings.nickname': 'Nickname',
|
|
68
|
+
'settings.nicknameSub': 'How the model addresses you',
|
|
69
|
+
'settings.nicknamePh': 'e.g. snow',
|
|
70
|
+
'settings.nicknameNote': 'Stored as a preference and attached to every turn; save empty to clear.',
|
|
71
|
+
'settings.shortcuts': 'Shortcuts',
|
|
72
|
+
'settings.shortcutsSub': 'Keys inside the composer',
|
|
73
|
+
'settings.groupSystem': 'System',
|
|
74
|
+
'settings.backend': 'Backend',
|
|
75
|
+
'settings.probing': 'probing…',
|
|
76
|
+
'settings.ok': 'OK',
|
|
77
|
+
'settings.retry': 'Retry',
|
|
78
|
+
'settings.updates': 'Updates',
|
|
79
|
+
'settings.groupUi': 'Interface',
|
|
80
|
+
'settings.language': 'Language',
|
|
81
|
+
'settings.languageSub': 'Switches interface copy instantly',
|
|
82
|
+
'settings.languageNote': 'Interface only — it does not change the language the model replies in.',
|
|
83
|
+
|
|
84
|
+
'settings.updNotEnabled': 'Off',
|
|
85
|
+
'settings.updAvailable': '{v} available',
|
|
86
|
+
'settings.updLatest': 'Up to date',
|
|
87
|
+
'settings.updFailed': 'Check failed',
|
|
88
|
+
'settings.updPending': 'Pending',
|
|
89
|
+
'settings.updHintOff': 'Off by default · set FOXCLAW_UPDATE_CHECK=1 to enable',
|
|
90
|
+
'settings.updHintError': 'Check failed (usage unaffected): {msg}',
|
|
91
|
+
'settings.updHintNew': 'Current v{cur} · latest v{latest}',
|
|
92
|
+
'settings.updHintOk': 'Current v{cur} · checked every 24h',
|
|
93
|
+
'settings.buildLocal': 'local build',
|
|
94
|
+
'settings.buildToday': 'today',
|
|
95
|
+
'settings.buildDays': '{n} days ago',
|
|
96
|
+
|
|
97
|
+
'settings.errSaveNick': 'Save failed: {msg}',
|
|
98
|
+
'settings.errSwitch': 'Switch failed: {msg}',
|
|
99
|
+
'settings.saidNick': 'I will call you {name} from now on',
|
|
100
|
+
'settings.saidNickCleared': 'Nickname cleared',
|
|
101
|
+
'settings.saidSwitched': 'Model switched to {label}',
|
|
102
|
+
'settings.saidStream': 'Streaming: token by token',
|
|
103
|
+
'settings.saidOrchestrate': 'Orchestrate: plan first, then execute step by step',
|
|
104
|
+
'settings.saidLang': 'Interface language set to {name}',
|
|
105
|
+
|
|
106
|
+
'chat.cmd.new': 'Start a new session',
|
|
107
|
+
'chat.cmd.stream': 'Switch to streaming chat',
|
|
108
|
+
'chat.cmd.orchestrate': 'Switch to plan-and-execute',
|
|
109
|
+
'chat.cmd.search': 'Search memory / knowledge / web: /search <query>',
|
|
110
|
+
'chat.cmd.ingest': 'Pick files to ingest into the library',
|
|
111
|
+
'chat.cmd.settings': 'Open settings',
|
|
112
|
+
'chat.cmd.stop': 'Stop the current generation',
|
|
113
|
+
'chat.cmd.clear': 'Clear this view only, backend untouched',
|
|
114
|
+
'chat.cmd.help': 'List all commands',
|
|
115
|
+
'chat.saidStream': 'Switched to streaming chat',
|
|
116
|
+
'chat.saidOrchestrate': 'Switched to plan-and-execute',
|
|
117
|
+
'chat.hintSlash': 'Commands',
|
|
118
|
+
'chat.hintAt': 'Mention a skill',
|
|
119
|
+
'chat.tagArg': 'takes an argument',
|
|
120
|
+
'chat.tagSkill': 'skill',
|
|
121
|
+
'chat.tagTool': 'tool',
|
|
122
|
+
'chat.unknownCmd': 'Unknown command: {head}',
|
|
123
|
+
'chat.ingestFailed': 'failed',
|
|
124
|
+
'chat.placeholder': 'Tell me what you need… / commands · @ skills · Enter to send',
|
|
125
|
+
'chat.send': 'Send',
|
|
126
|
+
'chat.stopGen': 'Stop generating',
|
|
127
|
+
|
|
128
|
+
'hero.title': 'Ask me anything',
|
|
129
|
+
'hero.cap': 'The supervisor agent dispatches sub-agents on demand; ask directly if you want it to read your library',
|
|
130
|
+
'hero.askName': 'What should I call you?',
|
|
131
|
+
'hero.namePh': 'e.g. snow',
|
|
132
|
+
'hero.confirm': 'Call me that',
|
|
133
|
+
'hero.skip': 'Skip',
|
|
134
|
+
'hero.skipTip': 'You can change this later in settings',
|
|
135
|
+
'hero.close': 'Close',
|
|
136
|
+
'hero.resume': 'Resume',
|
|
137
|
+
'hero.untitled': 'Untitled session',
|
|
138
|
+
'hero.msgs': '{n} messages',
|
|
139
|
+
'hero.recentKnowledge': 'Recent knowledge',
|
|
140
|
+
'hero.saidNick': 'Got it, I will call you {name}',
|
|
141
|
+
'hero.errSave': 'Save failed: {msg}',
|
|
142
|
+
'hero.q1': 'What skills are available right now?',
|
|
143
|
+
'hero.q2': 'Help me prioritise what I need to do today',
|
|
144
|
+
'hero.q3': 'Describe in one sentence what you can do for me',
|
|
145
|
+
|
|
146
|
+
'msg.supervisor': 'Supervisor',
|
|
147
|
+
'msg.generating': 'generating',
|
|
148
|
+
'msg.reasoning': 'Reasoning',
|
|
149
|
+
'msg.chars': '{n} chars',
|
|
150
|
+
'msg.plan': 'Plan',
|
|
151
|
+
'msg.steps': '{n} steps',
|
|
152
|
+
'msg.confidence': 'Confidence {n}%',
|
|
153
|
+
'msg.iterations': '{n} iterations',
|
|
154
|
+
'msg.evidence': 'Evidence',
|
|
155
|
+
'msg.items': '{n} items',
|
|
156
|
+
'msg.tool': 'tool',
|
|
157
|
+
'msg.copied': 'Copied',
|
|
158
|
+
'msg.copy': 'Copy',
|
|
159
|
+
'msg.retry': 'Retry',
|
|
160
|
+
'msg.srcMemory': 'memory',
|
|
161
|
+
'msg.srcKnowledge': 'knowledge',
|
|
162
|
+
'msg.srcWeb': 'web',
|
|
163
|
+
'msg.srcAgent': 'agent',
|
|
164
|
+
'msg.srcEvidence': 'evidence',
|
|
165
|
+
|
|
166
|
+
'key.enter': 'Send',
|
|
167
|
+
'key.shiftEnter': 'New line',
|
|
168
|
+
'key.slash': 'Command completion (e.g. /search)',
|
|
169
|
+
'key.at': 'Skill completion',
|
|
170
|
+
'key.arrows': 'Pick from the completion list',
|
|
171
|
+
'key.esc': 'Close completion / overlay',
|
|
172
|
+
'key.ctrlComma': 'Open settings',
|
|
173
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
'nav.overview': '概览',
|
|
3
|
+
'nav.activity': '活动',
|
|
4
|
+
'nav.tasks': '定时任务',
|
|
5
|
+
'nav.agents': '代理',
|
|
6
|
+
'nav.tools': '技能·连接器',
|
|
7
|
+
'nav.usage': '使用情况',
|
|
8
|
+
'nav.knowledge': '学习库',
|
|
9
|
+
'nav.review': '复习',
|
|
10
|
+
'nav.memory': '记忆中心',
|
|
11
|
+
'nav.settings': '设置',
|
|
12
|
+
|
|
13
|
+
'group.workspace': '工作台',
|
|
14
|
+
'group.capability': '能力',
|
|
15
|
+
'group.knowledge': '知识',
|
|
16
|
+
'group.system': '系统',
|
|
17
|
+
|
|
18
|
+
'common.refresh': '刷新',
|
|
19
|
+
'common.loading': '加载中…',
|
|
20
|
+
'common.offline': '后端未连接',
|
|
21
|
+
'common.offlinePanel': '后端未连接,这个面板暂时拉不到数据',
|
|
22
|
+
'common.online': '在线',
|
|
23
|
+
'common.offlineShort': '离线',
|
|
24
|
+
'common.save': '保存',
|
|
25
|
+
'common.notSet': '未设置',
|
|
26
|
+
'common.count': '{n} 条',
|
|
27
|
+
|
|
28
|
+
'rail.newSession': '开一个新会话',
|
|
29
|
+
'rail.newSessionBtn': '+ 新会话',
|
|
30
|
+
'rail.more': '更多',
|
|
31
|
+
'menu.title': '更多功能',
|
|
32
|
+
'menu.close': '关闭 (Esc)',
|
|
33
|
+
'rail.otherFeatures': '其它功能',
|
|
34
|
+
'rail.history': '会话历史',
|
|
35
|
+
'rail.empty': '还没有会话 · 发一条消息即开始',
|
|
36
|
+
'rail.untitled': '新会话',
|
|
37
|
+
'rail.rename': '重命名会话',
|
|
38
|
+
'rail.delete': '删除会话',
|
|
39
|
+
'rail.sessionTitle': '会话标题',
|
|
40
|
+
'rail.open': '打开{label}',
|
|
41
|
+
'rail.deleteConfirm': '删除会话「{name}」?\n对话历史会一起删掉,不可恢复。',
|
|
42
|
+
|
|
43
|
+
'app.expandInspector': '展开检视栏',
|
|
44
|
+
'app.inspector': '检视',
|
|
45
|
+
|
|
46
|
+
'topbar.systemStatus': '系统状态',
|
|
47
|
+
'topbar.newVersion': '有新版本 {latest}(当前 {current}),点这里看设置',
|
|
48
|
+
'topbar.planet': '打开 HKC 知识星球',
|
|
49
|
+
'topbar.planetBtn': '🌐 知识星球',
|
|
50
|
+
'topbar.settings': '设置 (Ctrl+,)',
|
|
51
|
+
|
|
52
|
+
'settings.title': '设置',
|
|
53
|
+
'settings.tag': 'Settings',
|
|
54
|
+
'settings.groupModel': '模型',
|
|
55
|
+
'settings.modelProvider': '模型与供应商',
|
|
56
|
+
'settings.modelProviderSub': '切换后服务端立即生效,不用重启',
|
|
57
|
+
'settings.current': '当前',
|
|
58
|
+
'settings.unconfigured': '未配置',
|
|
59
|
+
'settings.providerNote': '「未配置」= 后端缺该厂商的 Key。自定义模型的 Key / Base URL 在输入框左侧的模型胶囊里加。',
|
|
60
|
+
'settings.usage': '使用情况',
|
|
61
|
+
'settings.usageSub': 'token、调用次数、余额',
|
|
62
|
+
'settings.groupChat': '对话',
|
|
63
|
+
'settings.mode': '模式',
|
|
64
|
+
'settings.modeSub': '逐字流式 / 先出计划再逐步执行',
|
|
65
|
+
'settings.stream': '流式',
|
|
66
|
+
'settings.orchestrate': '编排',
|
|
67
|
+
'settings.nickname': '称呼',
|
|
68
|
+
'settings.nicknameSub': '模型会这么叫你',
|
|
69
|
+
'settings.nicknamePh': '例如:snow',
|
|
70
|
+
'settings.nicknameNote': '存成一条偏好,每轮对话都会带上;留空保存 = 清除。',
|
|
71
|
+
'settings.shortcuts': '快捷键',
|
|
72
|
+
'settings.shortcutsSub': '输入框里的键位',
|
|
73
|
+
'settings.groupSystem': '系统',
|
|
74
|
+
'settings.backend': '后端连接',
|
|
75
|
+
'settings.probing': '探测中…',
|
|
76
|
+
'settings.ok': '正常',
|
|
77
|
+
'settings.retry': '重试',
|
|
78
|
+
'settings.reprobe': '再探一次',
|
|
79
|
+
'settings.updates': '新版本',
|
|
80
|
+
'settings.groupUi': '界面',
|
|
81
|
+
'settings.language': '语言',
|
|
82
|
+
'settings.languageSub': '切换界面文案,立即生效',
|
|
83
|
+
'settings.languageNote': '只影响界面文字,不影响模型回复的语言。',
|
|
84
|
+
|
|
85
|
+
'settings.updNotEnabled': '未开启',
|
|
86
|
+
'settings.updAvailable': '新版本 {v}',
|
|
87
|
+
'settings.updLatest': '已是最新',
|
|
88
|
+
'settings.updFailed': '检查失败',
|
|
89
|
+
'settings.updPending': '待检查',
|
|
90
|
+
'settings.updHintOff': '默认关闭 · 设 FOXCLAW_UPDATE_CHECK=1 开启',
|
|
91
|
+
'settings.updHintError': '检查失败(不影响使用):{msg}',
|
|
92
|
+
'settings.updHintNew': '当前 v{cur} · 最新 v{latest}',
|
|
93
|
+
'settings.updHintOk': '当前 v{cur} · 24 小时查一次',
|
|
94
|
+
'settings.buildLocal': '本地构建',
|
|
95
|
+
'settings.buildToday': '今天',
|
|
96
|
+
'settings.buildDays': '{n} 天前',
|
|
97
|
+
|
|
98
|
+
'settings.errSaveNick': '保存失败:{msg}',
|
|
99
|
+
'settings.errSwitch': '切换失败:{msg}',
|
|
100
|
+
'settings.saidNick': '以后称呼你为 {name}',
|
|
101
|
+
'settings.saidNickCleared': '已清除称呼',
|
|
102
|
+
'settings.saidSwitched': '模型已切到 {label}',
|
|
103
|
+
'settings.saidStream': '流式:逐字输出',
|
|
104
|
+
'settings.saidOrchestrate': '编排:先出计划再逐步执行',
|
|
105
|
+
'settings.saidLang': '界面语言已切换为{name}',
|
|
106
|
+
|
|
107
|
+
'chat.cmd.new': '开一个新会话',
|
|
108
|
+
'chat.cmd.stream': '切到流式对话',
|
|
109
|
+
'chat.cmd.orchestrate': '切到编排任务',
|
|
110
|
+
'chat.cmd.search': '检索记忆/知识/联网:/搜索 关键词',
|
|
111
|
+
'chat.cmd.ingest': '选文件摄入知识库',
|
|
112
|
+
'chat.cmd.settings': '打开设置面板',
|
|
113
|
+
'chat.cmd.stop': '停止当前生成',
|
|
114
|
+
'chat.cmd.clear': '只清空当前显示,不动后端',
|
|
115
|
+
'chat.cmd.help': '列出全部命令',
|
|
116
|
+
'chat.saidStream': '已切到流式对话',
|
|
117
|
+
'chat.saidOrchestrate': '已切到编排任务',
|
|
118
|
+
'chat.hintSlash': '命令',
|
|
119
|
+
'chat.hintAt': '提及技能',
|
|
120
|
+
'chat.tagArg': '带参数',
|
|
121
|
+
'chat.tagSkill': '技能',
|
|
122
|
+
'chat.tagTool': '工具',
|
|
123
|
+
'chat.unknownCmd': '未知命令:{head}',
|
|
124
|
+
'chat.ingestFailed': '失败',
|
|
125
|
+
'chat.placeholder': '告诉我你想做什么… / 命令 · @ 技能 · Enter 发送',
|
|
126
|
+
'chat.send': '发送',
|
|
127
|
+
'chat.stopGen': '停止生成',
|
|
128
|
+
|
|
129
|
+
'hero.title': '问我任何事',
|
|
130
|
+
'hero.cap': '主管 Agent 会按需调度子 Agent;想让它读你的知识库,直接问就行',
|
|
131
|
+
'hero.askName': '我该怎么称呼你?',
|
|
132
|
+
'hero.namePh': '例如:snow',
|
|
133
|
+
'hero.confirm': '就这么叫',
|
|
134
|
+
'hero.skip': '跳过',
|
|
135
|
+
'hero.skipTip': '以后在设置里也能填',
|
|
136
|
+
'hero.close': '关闭',
|
|
137
|
+
'hero.resume': '继续上次',
|
|
138
|
+
'hero.untitled': '未命名会话',
|
|
139
|
+
'hero.msgs': '{n} 条消息',
|
|
140
|
+
'hero.recentKnowledge': '最近知识',
|
|
141
|
+
'hero.saidNick': '记住了,以后称呼你为 {name}',
|
|
142
|
+
'hero.errSave': '保存失败:{msg}',
|
|
143
|
+
'hero.q1': '现在系统里有哪些技能可以用?',
|
|
144
|
+
'hero.q2': '帮我把今天要做的事排个优先级',
|
|
145
|
+
'hero.q3': '用一句话说清你能帮我做什么',
|
|
146
|
+
|
|
147
|
+
'msg.supervisor': '主管 Agent',
|
|
148
|
+
'msg.generating': '生成中',
|
|
149
|
+
'msg.reasoning': '推理过程',
|
|
150
|
+
'msg.chars': '{n} 字',
|
|
151
|
+
'msg.plan': '执行计划',
|
|
152
|
+
'msg.steps': '{n} 步',
|
|
153
|
+
'msg.confidence': '置信度 {n}%',
|
|
154
|
+
'msg.iterations': '{n} 轮迭代',
|
|
155
|
+
'msg.evidence': '执行证据',
|
|
156
|
+
'msg.items': '{n} 项',
|
|
157
|
+
'msg.tool': '工具',
|
|
158
|
+
'msg.copied': '已复制',
|
|
159
|
+
'msg.copy': '复制',
|
|
160
|
+
'msg.retry': '重试',
|
|
161
|
+
'msg.srcMemory': '记忆',
|
|
162
|
+
'msg.srcKnowledge': '知识',
|
|
163
|
+
'msg.srcWeb': '联网',
|
|
164
|
+
'msg.srcAgent': '态势',
|
|
165
|
+
'msg.srcEvidence': '证据',
|
|
166
|
+
|
|
167
|
+
'key.enter': '发送',
|
|
168
|
+
'key.shiftEnter': '换行',
|
|
169
|
+
'key.slash': '命令补全(如 /搜索)',
|
|
170
|
+
'key.at': '技能补全',
|
|
171
|
+
'key.arrows': '在补全列表里选',
|
|
172
|
+
'key.esc': '关闭补全 / 浮层',
|
|
173
|
+
'key.ctrlComma': '打开设置',
|
|
174
|
+
}
|