linope 0.0.2__py3-none-any.whl
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.
- bindings/__init__.py +1 -0
- bindings/grpc_channel/__init__.py +68 -0
- bindings/nats_channel/__init__.py +72 -0
- bindings/support.py +35 -0
- bindings/zeromq_channel/__init__.py +68 -0
- capability/README.cn.md +51 -0
- capability/README.md +51 -0
- capability/context/README.cn.md +11 -0
- capability/context/README.md +11 -0
- capability/context/__init__.py +107 -0
- capability/context/context_compression/README.cn.md +11 -0
- capability/context/context_compression/README.md +11 -0
- capability/context/context_compression/semantic_compression/README.cn.md +79 -0
- capability/context/context_compression/semantic_compression/README.md +97 -0
- capability/context/context_compression/semantic_compression/capability_profile.py +25 -0
- capability/context/context_compression/semantic_compression/deterministic_pipeline.py +23 -0
- capability/context/context_compression/semantic_compression/json_args_truncation.py +60 -0
- capability/context/context_compression/semantic_compression/media_stripping.py +66 -0
- capability/context/context_compression/semantic_compression/old_tool_result_demotion.py +56 -0
- capability/context/context_compression/semantic_compression/proactive_prune_gate.py +29 -0
- capability/context/context_compression/semantic_compression/protected_tail_pressure.py +63 -0
- capability/context/context_compression/semantic_compression/skill_view_guard.py +117 -0
- capability/context/context_compression/semantic_compression/tool_pair_sanitizer.py +53 -0
- capability/context/context_compression/semantic_compression/tool_result_dedup.py +35 -0
- capability/context/context_compression/semantic_compression/tool_result_summary.py +82 -0
- capability/context/context_compression/sliding_window/README.cn.md +67 -0
- capability/context/context_compression/sliding_window/README.md +67 -0
- capability/context/context_compression/sliding_window/assistant_anchor.py +72 -0
- capability/context/context_compression/sliding_window/capability_profile.py +25 -0
- capability/context/context_compression/sliding_window/head_protection.py +87 -0
- capability/context/context_compression/sliding_window/last_n_users.py +52 -0
- capability/context/context_compression/sliding_window/preflight.py +30 -0
- capability/context/context_compression/sliding_window/tail_token_cut.py +127 -0
- capability/context/context_compression/sliding_window/tool_group_boundary.py +41 -0
- capability/context/context_compression/sliding_window/turn_pair.py +25 -0
- capability/context/context_compression/sliding_window/user_anchor.py +61 -0
- capability/context/context_compression/sliding_window/user_turns.py +88 -0
- capability/context/context_compression/summary_compression/README.cn.md +89 -0
- capability/context/context_compression/summary_compression/README.md +89 -0
- capability/context/context_compression/summary_compression/aggregate_input_bounder.py +36 -0
- capability/context/context_compression/summary_compression/auto_focus.py +38 -0
- capability/context/context_compression/summary_compression/capability_profile.py +25 -0
- capability/context/context_compression/summary_compression/compressed_transcript_assembler.py +131 -0
- capability/context/context_compression/summary_compression/handoff_helpers.py +147 -0
- capability/context/context_compression/summary_compression/latest_task_grounding.py +58 -0
- capability/context/context_compression/summary_compression/real_user_provenance.py +35 -0
- capability/context/context_compression/summary_compression/static_fallback.py +146 -0
- capability/context/context_compression/summary_compression/structured_prompt_builder.py +128 -0
- capability/context/context_compression/summary_compression/summary_budget.py +23 -0
- capability/context/context_compression/summary_compression/summary_runner.py +49 -0
- capability/context/context_compression/summary_compression/summary_text.py +84 -0
- capability/context/context_compression/summary_compression/turn_serializer.py +93 -0
- capability/model/README.cn.md +12 -0
- capability/model/README.md +12 -0
- capability/model/model_API/README.cn.md +10 -0
- capability/model/model_API/README.md +10 -0
- capability/model/model_API/model_interface/README.cn.md +46 -0
- capability/model/model_API/model_interface/README.md +46 -0
- capability/model/model_API/model_interface/anthropic.py +355 -0
- capability/model/model_API/model_interface/gemini.py +319 -0
- capability/model/model_API/model_interface/openai_chat.py +373 -0
- capability/model/model_API/model_interface/openai_response.py +364 -0
- capability/model/model_API/model_interface/roles.py +38 -0
- capability/model/model_API/model_interface/tests/call_api_test.py +290 -0
- capability/model/model_API/model_interface/tests/test_transcript.py +130 -0
- capability/model/model_API/model_paramaters/README.cn.md +14 -0
- capability/model/model_API/model_paramaters/README.md +14 -0
- capability/model/model_API/model_paramaters/context_limits/README.cn.md +30 -0
- capability/model/model_API/model_paramaters/context_limits/README.md +30 -0
- capability/model/model_API/model_paramaters/context_limits/context_limits.py +351 -0
- capability/model/model_API/model_paramaters/tests/test_context_limits.py +132 -0
- capability/model/model_API/model_paramaters/tests/test_tokens.py +73 -0
- capability/model/model_API/model_paramaters/tokens/README.cn.md +27 -0
- capability/model/model_API/model_paramaters/tokens/README.md +27 -0
- capability/model/model_API/model_paramaters/tokens/tokens.py +170 -0
- capability/model/model_message/README.cn.md +17 -0
- capability/model/model_message/README.md +17 -0
- capability/model/model_message/blocks.py +128 -0
- capability/model/model_message/tests/test_blocks.py +43 -0
- capability/model/model_provider/README.cn.md +96 -0
- capability/model/model_provider/README.md +96 -0
- capability/model/model_provider/anthropic_model/README.cn.md +22 -0
- capability/model/model_provider/anthropic_model/README.md +22 -0
- capability/model/model_provider/anthropic_model/anthropic_model.json +18 -0
- capability/model/model_provider/anthropic_model/anthropic_model_plugin.py +49 -0
- capability/model/model_provider/card_profile.py +104 -0
- capability/model/model_provider/gemini_model/README.cn.md +22 -0
- capability/model/model_provider/gemini_model/README.md +22 -0
- capability/model/model_provider/gemini_model/gemini_model.json +18 -0
- capability/model/model_provider/gemini_model/gemini_model_plugin.py +49 -0
- capability/model/model_provider/openai_chat_model/README.cn.md +22 -0
- capability/model/model_provider/openai_chat_model/README.md +22 -0
- capability/model/model_provider/openai_chat_model/openai_chat_model.json +22 -0
- capability/model/model_provider/openai_chat_model/openai_chat_model_plugin.py +53 -0
- capability/model/model_provider/openai_response_model/README.cn.md +22 -0
- capability/model/model_provider/openai_response_model/README.md +22 -0
- capability/model/model_provider/openai_response_model/openai_response_model.json +22 -0
- capability/model/model_provider/openai_response_model/openai_response_model_plugin.py +53 -0
- capability/model/model_provider/tests/test_card_profile.py +59 -0
- capability/model/model_runtime/README.cn.md +37 -0
- capability/model/model_runtime/README.md +37 -0
- capability/model/model_runtime/assembler.py +104 -0
- capability/model/model_runtime/blocks.py +114 -0
- capability/model/model_runtime/call_model.py +230 -0
- capability/model/model_runtime/model_main.py +289 -0
- capability/model/model_runtime/tests/test_blocks.py +76 -0
- capability/model/model_runtime/tests/test_call_model.py +119 -0
- capability/model/model_runtime/tests/test_model_main.py +78 -0
- capability/model/model_runtime/usage.py +54 -0
- capability/process_adapter.py +158 -0
- capability/prompt/README.cn.md +9 -0
- capability/prompt/README.md +9 -0
- capability/prompt/prompt_card/system/README.cn.md +31 -0
- capability/prompt/prompt_card/system/README.md +31 -0
- capability/prompt/prompt_card/system/identity.md +3 -0
- capability/prompt/prompt_card/system/system_02_tools.md +59 -0
- capability/sandbox/README.cn.md +20 -0
- capability/sandbox/README.md +20 -0
- capability/sandbox/sandbox/README.cn.md +23 -0
- capability/sandbox/sandbox/README.md +23 -0
- capability/sandbox/sandbox/src/escalation_plugin.py +129 -0
- capability/sandbox/sandbox/src/roots_plugin.py +48 -0
- capability/sandbox/sandbox/src/sandbox_plugin.py +151 -0
- capability/sandbox/sandbox/tests/escalation_test.py +192 -0
- capability/sandbox/sandbox/tests/roots_test.py +60 -0
- capability/sandbox/sandbox/tests/vocabulary_test.py +75 -0
- capability/sandbox/sandbox-local/README.cn.md +11 -0
- capability/sandbox/sandbox-local/README.md +11 -0
- capability/sandbox/sandbox-local/src/profiles_plugin.py +55 -0
- capability/sandbox/sandbox-local/src/sandbox_local_plugin.py +239 -0
- capability/sandbox/sandbox-local/tests/local_test.py +72 -0
- capability/sandbox/sandbox-policy/README.cn.md +16 -0
- capability/sandbox/sandbox-policy/README.md +16 -0
- capability/sandbox/sandbox-policy/src/sandbox_policy_plugin.py +159 -0
- capability/sandbox/sandbox-policy/src/session_mode_plugin.py +81 -0
- capability/sandbox/sandbox-policy/tests/policy_test.py +149 -0
- capability/sandbox/sandbox-policy/tests/session_mode_test.py +69 -0
- capability/sandbox/sandbox-windows-acl/README.cn.md +15 -0
- capability/sandbox/sandbox-windows-acl/README.md +15 -0
- capability/sandbox/sandbox-windows-acl/src/acl_plugin.py +189 -0
- capability/sandbox/sandbox-windows-acl/src/errors_plugin.py +19 -0
- capability/sandbox/sandbox-windows-acl/src/ffi_plugin.py +602 -0
- capability/sandbox/sandbox-windows-acl/src/grant_plugin.py +87 -0
- capability/sandbox/sandbox-windows-acl/src/path_boundary_plugin.py +37 -0
- capability/sandbox/sandbox-windows-acl/src/runner_plugin.py +212 -0
- capability/sandbox/sandbox-windows-acl/src/spawn_plugin.py +260 -0
- capability/sandbox/sandbox-windows-acl/src/token_plugin.py +179 -0
- capability/sandbox/sandbox-windows-acl/src/win32_abi_plugin.py +74 -0
- capability/sandbox/sandbox-windows-acl/src/windows_acl_plugin.py +264 -0
- capability/sandbox/sandbox-windows-acl/src/workspace_sid_plugin.py +30 -0
- capability/sandbox/sandbox-windows-acl/tests/errors_test.py +29 -0
- capability/sandbox/sandbox-windows-acl/tests/path_boundary_test.py +68 -0
- capability/sandbox/sandbox-windows-acl/tests/quote_test.py +44 -0
- capability/sandbox/sandbox-windows-acl/tests/runner_parse_test.py +41 -0
- capability/sandbox/sandbox-windows-acl/tests/workspace_sid_test.py +47 -0
- capability/sandbox/workspace/README.cn.md +18 -0
- capability/sandbox/workspace/README.md +18 -0
- capability/sandbox/workspace/src/backend_plugin.py +115 -0
- capability/sandbox/workspace/src/dockerfile_plugin.py +92 -0
- capability/sandbox/workspace/src/workspace_plugin.py +289 -0
- capability/sandbox/workspace/tests/workspace_test.py +416 -0
- capability/tools/README.cn.md +12 -0
- capability/tools/README.md +12 -0
- capability/tools/agent_tools/README.cn.md +14 -0
- capability/tools/agent_tools/README.md +14 -0
- capability/tools/agent_tools/code_tools/README.cn.md +33 -0
- capability/tools/agent_tools/code_tools/README.md +33 -0
- capability/tools/agent_tools/code_tools/run_code_plugin.py +272 -0
- capability/tools/agent_tools/file_tools/README.cn.md +37 -0
- capability/tools/agent_tools/file_tools/README.md +37 -0
- capability/tools/agent_tools/file_tools/edit_plugin.py +115 -0
- capability/tools/agent_tools/file_tools/file_plugin.py +2831 -0
- capability/tools/agent_tools/file_tools/glob_plugin.py +116 -0
- capability/tools/agent_tools/file_tools/grep_plugin.py +185 -0
- capability/tools/agent_tools/file_tools/read_image_plugin.py +99 -0
- capability/tools/agent_tools/file_tools/read_plugin.py +122 -0
- capability/tools/agent_tools/file_tools/str_replace_editor_plugin.py +223 -0
- capability/tools/agent_tools/file_tools/tests/read_test.py +74 -0
- capability/tools/agent_tools/file_tools/write_plugin.py +85 -0
- capability/tools/agent_tools/interaction_tools/README.cn.md +33 -0
- capability/tools/agent_tools/interaction_tools/README.md +33 -0
- capability/tools/agent_tools/interaction_tools/ask_user_plugin.py +138 -0
- capability/tools/agent_tools/shell_tools/README.cn.md +35 -0
- capability/tools/agent_tools/shell_tools/README.md +35 -0
- capability/tools/agent_tools/shell_tools/bash_persistent_plugin.py +151 -0
- capability/tools/agent_tools/shell_tools/bash_plugin.py +262 -0
- capability/tools/agent_tools/shell_tools/pwsh_plugin.py +274 -0
- capability/tools/agent_tools/terminal_tools/README.cn.md +44 -0
- capability/tools/agent_tools/terminal_tools/README.md +44 -0
- capability/tools/agent_tools/terminal_tools/terminal_close_plugin.py +72 -0
- capability/tools/agent_tools/terminal_tools/terminal_close_session_plugin.py +71 -0
- capability/tools/agent_tools/terminal_tools/terminal_focus_plugin.py +75 -0
- capability/tools/agent_tools/terminal_tools/terminal_list_plugin.py +60 -0
- capability/tools/agent_tools/terminal_tools/terminal_open_plugin.py +93 -0
- capability/tools/agent_tools/terminal_tools/terminal_plugin.py +3781 -0
- capability/tools/agent_tools/terminal_tools/terminal_preview_plugin.py +94 -0
- capability/tools/agent_tools/terminal_tools/terminal_read_plugin.py +92 -0
- capability/tools/agent_tools/terminal_tools/terminal_read_session_plugin.py +89 -0
- capability/tools/agent_tools/terminal_tools/terminal_send_plugin.py +108 -0
- capability/tools/agent_tools/terminal_tools/terminal_signal_plugin.py +89 -0
- capability/tools/agent_tools/web_search_tools/README.cn.md +36 -0
- capability/tools/agent_tools/web_search_tools/README.md +36 -0
- capability/tools/agent_tools/web_search_tools/brave_free_plugin.py +174 -0
- capability/tools/agent_tools/web_search_tools/ddgs_plugin.py +114 -0
- capability/tools/agent_tools/web_search_tools/exa_plugin.py +185 -0
- capability/tools/agent_tools/web_search_tools/firecrawl_plugin.py +195 -0
- capability/tools/agent_tools/web_search_tools/parallel_plugin.py +183 -0
- capability/tools/agent_tools/web_search_tools/searxng_plugin.py +170 -0
- capability/tools/agent_tools/web_search_tools/tavily_plugin.py +171 -0
- capability/tools/external_tools/ci_tools/README.cn.md +15 -0
- capability/tools/external_tools/ci_tools/README.md +15 -0
- capability/tools/external_tools/ci_tools/generate/README.cn.md +26 -0
- capability/tools/external_tools/ci_tools/generate/README.md +26 -0
- capability/tools/external_tools/ci_tools/generate/compose/README.cn.md +19 -0
- capability/tools/external_tools/ci_tools/generate/compose/README.md +19 -0
- capability/tools/external_tools/ci_tools/generate/compose/architecture_card/list.json +25 -0
- capability/tools/external_tools/ci_tools/generate/compose/architecture_card/list.md +36 -0
- capability/tools/external_tools/ci_tools/generate/compose/architecture_card/list.toml +35 -0
- capability/tools/external_tools/ci_tools/generate/compose/compose_generate.py +215 -0
- capability/tools/external_tools/ci_tools/generate/plugin/README.cn.md +164 -0
- capability/tools/external_tools/ci_tools/generate/plugin/README.md +164 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/assembly_check.py +528 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/descriptor_check.py +371 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/kernel_check.py +288 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/lip_check.py +177 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/provider_config_check.py +124 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/sdk_boundary_check.py +120 -0
- capability/tools/external_tools/ci_tools/generate/plugin/host_sibling/surface_check.py +251 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/allow_list/allow_check.py +143 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/allow_list/allow_list_card/list.json +126 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/allow_list/allow_list_card/list.md +40 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/allow_list/allow_list_card/list.toml +36 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/allow_list/allow_list_generate.py +332 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/deny_list/deny_check.py +267 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/deny_list/deny_list_crad/list.json +58 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/deny_list/deny_list_crad/list.md +58 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/deny_list/deny_list_crad/list.toml +56 -0
- capability/tools/external_tools/ci_tools/generate/plugin/list/deny_list/deny_list_generate.py +109 -0
- capability/tools/external_tools/ci_tools/generate/plugin/plugin_generate.py +427 -0
- capability/tools/external_tools/ci_tools/generate/process/README.cn.md +19 -0
- capability/tools/external_tools/ci_tools/generate/process/README.md +19 -0
- capability/tools/external_tools/ci_tools/generate/process/architecture_card/list.json +30 -0
- capability/tools/external_tools/ci_tools/generate/process/architecture_card/list.md +41 -0
- capability/tools/external_tools/ci_tools/generate/process/architecture_card/list.toml +42 -0
- capability/tools/external_tools/ci_tools/generate/process/process_generate.py +212 -0
- capability/tools/external_tools/ci_tools/generate/services/README.cn.md +19 -0
- capability/tools/external_tools/ci_tools/generate/services/README.md +19 -0
- capability/tools/external_tools/ci_tools/generate/services/architecture_card/list.json +30 -0
- capability/tools/external_tools/ci_tools/generate/services/architecture_card/list.md +43 -0
- capability/tools/external_tools/ci_tools/generate/services/architecture_card/list.toml +44 -0
- capability/tools/external_tools/ci_tools/generate/services/services_generate.py +209 -0
- capability/tools/external_tools/mcp/README.cn.md +42 -0
- capability/tools/external_tools/mcp/README.md +42 -0
- capability/tools/external_tools/mcp/mcp_auth_security_plugin.py +363 -0
- capability/tools/external_tools/mcp/mcp_client.py +98 -0
- capability/tools/external_tools/mcp/mcp_client_lifecycle.py +325 -0
- capability/tools/external_tools/mcp/mcp_config_plugin.py +448 -0
- capability/tools/external_tools/mcp/mcp_content_plugin.py +245 -0
- capability/tools/external_tools/mcp/mcp_host_manager_plugin.py +509 -0
- capability/tools/external_tools/mcp/mcp_interaction_plugin.py +374 -0
- capability/tools/external_tools/mcp/mcp_protocol_plugin.py +238 -0
- capability/tools/external_tools/mcp/mcp_resilience_plugin.py +359 -0
- capability/tools/external_tools/mcp/mcp_runtime.py +202 -0
- capability/tools/external_tools/mcp/mcp_servers.json +8 -0
- capability/tools/external_tools/mcp/mcp_tool_manager_plugin.py +480 -0
- capability/tools/external_tools/mcp/mcp_transport/README.cn.md +17 -0
- capability/tools/external_tools/mcp/mcp_transport/README.md +17 -0
- capability/tools/external_tools/mcp/mcp_transport/sse.py +161 -0
- capability/tools/external_tools/mcp/mcp_transport/stdio.py +145 -0
- capability/tools/external_tools/mcp/mcp_transport/streamable_http.py +223 -0
- kernel/README.cn.md +20 -0
- kernel/README.md +20 -0
- kernel/calculate/README.cn.md +20 -0
- kernel/calculate/README.md +20 -0
- kernel/calculate/__init__.py +5 -0
- kernel/calculate/measure.py +124 -0
- kernel/command/README.cn.md +103 -0
- kernel/command/README.md +103 -0
- kernel/command/__init__.py +21 -0
- kernel/command/__main__.py +8 -0
- kernel/command/convention.py +81 -0
- kernel/command/dispatch.py +79 -0
- kernel/command/file/README.cn.md +19 -0
- kernel/command/file/README.md +19 -0
- kernel/command/file/__init__.py +0 -0
- kernel/command/file/create.py +69 -0
- kernel/command/file/env.py +28 -0
- kernel/command/log.py +47 -0
- kernel/command/memory.py +44 -0
- kernel/command/parser.py +144 -0
- kernel/command/process/README.cn.md +63 -0
- kernel/command/process/README.md +63 -0
- kernel/command/process/__init__.py +0 -0
- kernel/command/process/clerk.py +219 -0
- kernel/command/process/listen.py +703 -0
- kernel/command/process/process.py +58 -0
- kernel/command/process/start.py +219 -0
- kernel/command/process/talk.py +24 -0
- kernel/command/screen/README.cn.md +50 -0
- kernel/command/screen/README.md +50 -0
- kernel/command/screen/__init__.py +0 -0
- kernel/command/screen/live_stream.py +13 -0
- kernel/command/screen/resource.py +49 -0
- kernel/command/service.py +161 -0
- kernel/command/window.py +35 -0
- kernel/communication/README.cn.md +38 -0
- kernel/communication/README.md +38 -0
- kernel/communication/__init__.py +1 -0
- kernel/communication/address.py +29 -0
- kernel/communication/channel.py +106 -0
- kernel/communication/offers.py +104 -0
- kernel/communication/page.py +75 -0
- kernel/communication/verify.py +422 -0
- kernel/environment/README.cn.md +71 -0
- kernel/environment/README.md +71 -0
- kernel/environment/__init__.py +15 -0
- kernel/environment/compute.py +156 -0
- kernel/environment/confine.py +112 -0
- kernel/environment/current.py +31 -0
- kernel/environment/file_io.py +49 -0
- kernel/environment/filesystem.py +144 -0
- kernel/environment/host_adapter.py +56 -0
- kernel/environment/identity.py +113 -0
- kernel/environment/lifecycle.py +132 -0
- kernel/environment/mount.py +158 -0
- kernel/environment/policy.py +87 -0
- kernel/environment/room.py +128 -0
- kernel/environment/sandbox_vocab.py +93 -0
- kernel/environment/session_mode.py +62 -0
- kernel/environment/shell.py +205 -0
- kernel/hypermedia/README.cn.md +100 -0
- kernel/hypermedia/README.md +100 -0
- kernel/hypermedia/__init__.py +41 -0
- kernel/hypermedia/file_link.py +14 -0
- kernel/hypermedia/follow.py +12 -0
- kernel/hypermedia/handle.py +15 -0
- kernel/hypermedia/http_server.py +456 -0
- kernel/hypermedia/link.py +24 -0
- kernel/hypermedia/link_selector.py +47 -0
- kernel/hypermedia/memory_page.py +72 -0
- kernel/hypermedia/process_page.py +53 -0
- kernel/hypermedia/representation.py +24 -0
- kernel/hypermedia/representation_json.py +104 -0
- kernel/hypermedia/uri.py +79 -0
- kernel/load_balancing/README.cn.md +43 -0
- kernel/load_balancing/README.md +43 -0
- kernel/load_balancing/__init__.py +11 -0
- kernel/load_balancing/hints.py +62 -0
- kernel/load_balancing/inflight.py +73 -0
- kernel/load_balancing/pick.py +26 -0
- kernel/load_balancing/process_scale.py +62 -0
- kernel/load_balancing/relieve.py +40 -0
- kernel/load_balancing/route.py +5 -0
- kernel/load_balancing/workers.py +165 -0
- kernel/process/README.cn.md +54 -0
- kernel/process/README.md +54 -0
- kernel/process/__init__.py +1 -0
- kernel/process/declaration.py +116 -0
- kernel/process/ledger.py +94 -0
- kernel/process/process_creat/README.cn.md +15 -0
- kernel/process/process_creat/README.md +15 -0
- kernel/process/process_creat/__init__.py +19 -0
- kernel/process/process_creat/activation.py +81 -0
- kernel/process/process_creat/instances.py +151 -0
- kernel/process/process_manager/README.cn.md +45 -0
- kernel/process/process_manager/README.md +45 -0
- kernel/process/process_manager/__init__.py +9 -0
- kernel/process/process_manager/capability_process.py +442 -0
- kernel/process/process_manager/client.py +30 -0
- kernel/process/process_manager/handle.py +16 -0
- kernel/process/process_manager/lifecycle.py +12 -0
- kernel/process/process_manager/liveness.py +94 -0
- kernel/process/process_manager/monitor.py +26 -0
- kernel/process/process_manager/reaper.py +29 -0
- kernel/process/process_manager/tool_dispatch.py +75 -0
- kernel/process/process_runtime/README.cn.md +29 -0
- kernel/process/process_runtime/README.md +29 -0
- kernel/process/process_runtime/__init__.py +27 -0
- kernel/process/process_runtime/__main__.py +6 -0
- kernel/process/process_runtime/adapter.py +31 -0
- kernel/process/process_runtime/runtime.py +274 -0
- kernel/process/profile.py +47 -0
- kernel/process/profiles.py +148 -0
- kernel/process/reconcile.py +232 -0
- kernel/process/resource_record.py +223 -0
- kernel/process/tests/test_command_convention.py +13 -0
- kernel/process/tests/test_thread_runtime.py +215 -0
- kernel/resource/README.cn.md +56 -0
- kernel/resource/README.md +56 -0
- kernel/resource/__init__.py +56 -0
- kernel/resource/compile.py +120 -0
- kernel/resource/definition.py +121 -0
- kernel/resource/handle_view.py +85 -0
- kernel/resource/lease.py +244 -0
- kernel/resource/memory/README.cn.md +68 -0
- kernel/resource/memory/README.md +68 -0
- kernel/resource/memory/__init__.py +11 -0
- kernel/resource/memory/backends.py +439 -0
- kernel/resource/memory/fit.py +130 -0
- kernel/resource/memory/footprint.py +42 -0
- kernel/resource/memory/records.py +99 -0
- kernel/resource/memory/runtime.py +277 -0
- kernel/resource/memory/state.py +14 -0
- kernel/resource/memory/store.py +5 -0
- kernel/resource/memory/token_meter.py +16 -0
- kernel/resource/pool.py +205 -0
- kernel/resource/resource_contract.py +137 -0
- kernel/scheduler/README.cn.md +64 -0
- kernel/scheduler/README.md +64 -0
- kernel/scheduler/__init__.py +23 -0
- kernel/scheduler/access.py +256 -0
- kernel/scheduler/memory_space.py +195 -0
- kernel/scheduler/model_turn.py +356 -0
- kernel/scheduler/requests.py +53 -0
- kernel/scheduler/route.py +93 -0
- kernel/scheduler/threads.py +70 -0
- kernel/services/README.cn.md +34 -0
- kernel/services/README.md +34 -0
- kernel/services/__init__.py +5 -0
- kernel/services/collection.py +79 -0
- kernel/thread/README.cn.md +55 -0
- kernel/thread/README.md +55 -0
- kernel/thread/__init__.py +23 -0
- kernel/thread/contracts.py +113 -0
- kernel/thread/limiter.py +41 -0
- kernel/thread/runtime.py +216 -0
- kernel/trace/README.cn.md +22 -0
- kernel/trace/README.md +22 -0
- kernel/trace/__init__.py +32 -0
- kernel/trace/activity.py +68 -0
- kernel/trace/journal.py +42 -0
- linope-0.0.2.dist-info/METADATA +87 -0
- linope-0.0.2.dist-info/RECORD +454 -0
- linope-0.0.2.dist-info/WHEEL +5 -0
- linope-0.0.2.dist-info/entry_points.txt +2 -0
- linope-0.0.2.dist-info/licenses/LICENSE +201 -0
- linope-0.0.2.dist-info/top_level.txt +4 -0
- tui/README.cn.md +79 -0
- tui/README.md +79 -0
- tui/__init__.py +0 -0
- tui/banner.ts +39 -0
- tui/bin.js +33 -0
- tui/editor.check.ts +65 -0
- tui/editor.ts +127 -0
- tui/focus.check.ts +26 -0
- tui/focus.ts +82 -0
- tui/keys.ts +141 -0
- tui/launch.py +56 -0
- tui/link/events.ts +57 -0
- tui/link/session.ts +89 -0
- tui/main.ts +430 -0
- tui/screen.check.ts +139 -0
- tui/screen.ts +646 -0
- tui/theme.ts +33 -0
bindings/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Transports a caller may open. The kernel does not import this package."""
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Remote call with grpcio. One generic method carries the message as JSON bytes.
|
|
2
|
+
|
|
3
|
+
The directory is named ``grpc_channel`` so it does not hide the ``grpc`` package.
|
|
4
|
+
The kernel does not import or open this transport.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from concurrent import futures
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from bindings.support import Inbox, needs
|
|
14
|
+
|
|
15
|
+
_METHOD = "/linope.Channel/Send"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GrpcChannel:
|
|
19
|
+
"""``addresses`` maps an address string to ``host:port``. ``send`` waits for the seq."""
|
|
20
|
+
|
|
21
|
+
name = "grpc"
|
|
22
|
+
|
|
23
|
+
def __init__(self, addresses: dict[str, str] | None = None, timeout: float = 10.0) -> None:
|
|
24
|
+
self._grpc = needs("grpcio", "grpc")
|
|
25
|
+
self._addresses = {str(pid): str(address) for pid, address in (addresses or {}).items()}
|
|
26
|
+
self._timeout = float(timeout)
|
|
27
|
+
self._inboxes: dict[str, Inbox] = {}
|
|
28
|
+
self._servers: list[Any] = []
|
|
29
|
+
|
|
30
|
+
def listen(self, me: str, address: str = "127.0.0.1:0") -> str:
|
|
31
|
+
"""Serve this address's inbox and return the address others call."""
|
|
32
|
+
grpc = self._grpc
|
|
33
|
+
inbox = self._inboxes.setdefault(str(me), Inbox())
|
|
34
|
+
|
|
35
|
+
def take(request: bytes, context: Any) -> bytes:
|
|
36
|
+
del context
|
|
37
|
+
return str(inbox.put(json.loads(request.decode("utf-8")))).encode("utf-8")
|
|
38
|
+
|
|
39
|
+
handler = grpc.method_handlers_generic_handler(
|
|
40
|
+
"linope.Channel",
|
|
41
|
+
{"Send": grpc.unary_unary_rpc_method_handler(take)},
|
|
42
|
+
)
|
|
43
|
+
server = grpc.server(futures.ThreadPoolExecutor(max_workers=2))
|
|
44
|
+
server.add_generic_rpc_handlers((handler,))
|
|
45
|
+
host = address.rsplit(":", 1)[0]
|
|
46
|
+
port = server.add_insecure_port(address)
|
|
47
|
+
server.start()
|
|
48
|
+
self._servers.append(server)
|
|
49
|
+
bound = f"{host}:{port}"
|
|
50
|
+
self._addresses[str(me)] = bound
|
|
51
|
+
return bound
|
|
52
|
+
|
|
53
|
+
def send(self, to: str, message: dict[str, Any], sender: str = "") -> str:
|
|
54
|
+
address = self._addresses.get(str(to))
|
|
55
|
+
if not address:
|
|
56
|
+
raise LookupError(f"不知道这个地址: {to}")
|
|
57
|
+
payload = json.dumps({**message, "sender": sender}, ensure_ascii=False).encode("utf-8")
|
|
58
|
+
with self._grpc.insecure_channel(address) as remote:
|
|
59
|
+
call = remote.unary_unary(_METHOD)
|
|
60
|
+
return call(payload, timeout=self._timeout).decode("utf-8")
|
|
61
|
+
|
|
62
|
+
def receive(self, me: str, after: int = 0) -> list[dict[str, Any]]:
|
|
63
|
+
return self._inboxes.setdefault(str(me), Inbox()).after(after)
|
|
64
|
+
|
|
65
|
+
def close(self) -> None:
|
|
66
|
+
for server in self._servers:
|
|
67
|
+
server.stop(grace=None)
|
|
68
|
+
self._servers.clear()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Queue and topics with nats-py. One address listens on ``linope.<address>``.
|
|
2
|
+
|
|
3
|
+
A NATS server must already be running. The default address is
|
|
4
|
+
``nats://127.0.0.1:4222``. The kernel does not import or open this transport.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import json
|
|
11
|
+
import threading
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from bindings.support import Inbox, needs
|
|
15
|
+
|
|
16
|
+
DEFAULT_SERVER = "nats://127.0.0.1:4222"
|
|
17
|
+
BROADCAST = "linope.all"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class NatsChannel:
|
|
21
|
+
"""One connection on its own event loop thread. ``send`` does not wait for a reply."""
|
|
22
|
+
|
|
23
|
+
name = "nats"
|
|
24
|
+
|
|
25
|
+
def __init__(self, server: str = DEFAULT_SERVER, timeout: float = 5.0) -> None:
|
|
26
|
+
self._nats = needs("nats-py", "nats")
|
|
27
|
+
self._server = server
|
|
28
|
+
self._timeout = float(timeout)
|
|
29
|
+
self._inboxes: dict[str, Inbox] = {}
|
|
30
|
+
self._loop = asyncio.new_event_loop()
|
|
31
|
+
self._thread = threading.Thread(target=self._loop.run_forever, name="nats-channel", daemon=True)
|
|
32
|
+
self._thread.start()
|
|
33
|
+
self._client = self._run(self._nats.connect(server, connect_timeout=self._timeout))
|
|
34
|
+
|
|
35
|
+
def listen(self, me: str) -> str:
|
|
36
|
+
"""Subscribe this address to its subject and return the subject."""
|
|
37
|
+
inbox = self._inboxes.setdefault(str(me), Inbox())
|
|
38
|
+
|
|
39
|
+
async def take(message: Any) -> None:
|
|
40
|
+
inbox.put(json.loads(message.data.decode("utf-8")))
|
|
41
|
+
|
|
42
|
+
subject = f"linope.{me}"
|
|
43
|
+
self._run(self._client.subscribe(subject, cb=take))
|
|
44
|
+
self._run(self._client.subscribe(BROADCAST, cb=take))
|
|
45
|
+
return subject
|
|
46
|
+
|
|
47
|
+
def send(self, to: str, message: dict[str, Any], sender: str = "") -> str:
|
|
48
|
+
self.publish(f"linope.{to}", message, sender)
|
|
49
|
+
return ""
|
|
50
|
+
|
|
51
|
+
def publish(self, topic: str, message: dict[str, Any], sender: str = "") -> None:
|
|
52
|
+
"""Deliver one message to this topic. The topic string is used as given."""
|
|
53
|
+
payload = json.dumps({**message, "sender": sender}, ensure_ascii=False).encode("utf-8")
|
|
54
|
+
self._run(self._client.publish(str(topic), payload))
|
|
55
|
+
self._run(self._client.flush(timeout=self._timeout))
|
|
56
|
+
|
|
57
|
+
def broadcast(self, message: dict[str, Any], sender: str = "") -> None:
|
|
58
|
+
"""Every address that called ``listen`` sees this one message."""
|
|
59
|
+
self.publish(BROADCAST, message, sender)
|
|
60
|
+
|
|
61
|
+
def receive(self, me: str, after: int = 0) -> list[dict[str, Any]]:
|
|
62
|
+
return self._inboxes.setdefault(str(me), Inbox()).after(after)
|
|
63
|
+
|
|
64
|
+
def close(self) -> None:
|
|
65
|
+
try:
|
|
66
|
+
self._run(self._client.drain())
|
|
67
|
+
finally:
|
|
68
|
+
self._loop.call_soon_threadsafe(self._loop.stop)
|
|
69
|
+
self._thread.join(timeout=1)
|
|
70
|
+
|
|
71
|
+
def _run(self, coroutine: Any) -> Any:
|
|
72
|
+
return asyncio.run_coroutine_threadsafe(coroutine, self._loop).result(self._timeout + 1)
|
bindings/support.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Small pieces the transports share. The kernel does not import them."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def needs(package: str, module: str) -> Any:
|
|
9
|
+
"""Import a library a transport is built on, or say which package to install."""
|
|
10
|
+
import importlib
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
return importlib.import_module(module)
|
|
14
|
+
except ImportError as exc:
|
|
15
|
+
raise RuntimeError(f"这个通道要先安装 {package}: pip install {package}") from exc
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Inbox:
|
|
19
|
+
"""Received messages for one address, numbered as they arrive."""
|
|
20
|
+
|
|
21
|
+
def __init__(self) -> None:
|
|
22
|
+
import threading
|
|
23
|
+
|
|
24
|
+
self._lock = threading.Lock()
|
|
25
|
+
self._rows: list[dict[str, Any]] = []
|
|
26
|
+
|
|
27
|
+
def put(self, message: dict[str, Any]) -> int:
|
|
28
|
+
with self._lock:
|
|
29
|
+
seq = len(self._rows) + 1
|
|
30
|
+
self._rows.append({**message, "seq": seq})
|
|
31
|
+
return seq
|
|
32
|
+
|
|
33
|
+
def after(self, seq: int) -> list[dict[str, Any]]:
|
|
34
|
+
with self._lock:
|
|
35
|
+
return [dict(row) for row in self._rows if row["seq"] > int(seq)]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Point to point with pyzmq. Each address binds a PULL socket.
|
|
2
|
+
|
|
3
|
+
The kernel does not import or open this transport.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import threading
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from bindings.support import Inbox, needs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ZeroMqChannel:
|
|
16
|
+
"""``addresses`` maps an address string to ``tcp://host:port``. ``send`` does not wait."""
|
|
17
|
+
|
|
18
|
+
name = "zeromq"
|
|
19
|
+
|
|
20
|
+
def __init__(self, addresses: dict[str, str] | None = None) -> None:
|
|
21
|
+
self._zmq = needs("pyzmq", "zmq")
|
|
22
|
+
self._context = self._zmq.Context.instance()
|
|
23
|
+
self._addresses = {str(pid): str(address) for pid, address in (addresses or {}).items()}
|
|
24
|
+
self._inboxes: dict[str, Inbox] = {}
|
|
25
|
+
self._threads: list[threading.Thread] = []
|
|
26
|
+
self._stop = threading.Event()
|
|
27
|
+
|
|
28
|
+
def listen(self, me: str, address: str = "tcp://127.0.0.1:*") -> str:
|
|
29
|
+
"""Bind this address's socket and return the address others send to."""
|
|
30
|
+
socket = self._context.socket(self._zmq.PULL)
|
|
31
|
+
socket.bind(address)
|
|
32
|
+
bound = socket.getsockopt_string(self._zmq.LAST_ENDPOINT)
|
|
33
|
+
self._addresses[str(me)] = bound
|
|
34
|
+
inbox = self._inboxes.setdefault(str(me), Inbox())
|
|
35
|
+
thread = threading.Thread(target=self._drain, args=(socket, inbox), daemon=True)
|
|
36
|
+
thread.start()
|
|
37
|
+
self._threads.append(thread)
|
|
38
|
+
return bound
|
|
39
|
+
|
|
40
|
+
def send(self, to: str, message: dict[str, Any], sender: str = "") -> str:
|
|
41
|
+
address = self._addresses.get(str(to))
|
|
42
|
+
if not address:
|
|
43
|
+
raise LookupError(f"不知道这个地址: {to}")
|
|
44
|
+
socket = self._context.socket(self._zmq.PUSH)
|
|
45
|
+
try:
|
|
46
|
+
socket.connect(address)
|
|
47
|
+
socket.send_string(json.dumps({**message, "sender": sender}, ensure_ascii=False))
|
|
48
|
+
finally:
|
|
49
|
+
socket.close(linger=1000)
|
|
50
|
+
return ""
|
|
51
|
+
|
|
52
|
+
def receive(self, me: str, after: int = 0) -> list[dict[str, Any]]:
|
|
53
|
+
return self._inboxes.setdefault(str(me), Inbox()).after(after)
|
|
54
|
+
|
|
55
|
+
def close(self) -> None:
|
|
56
|
+
self._stop.set()
|
|
57
|
+
for thread in self._threads:
|
|
58
|
+
thread.join(timeout=1)
|
|
59
|
+
|
|
60
|
+
def _drain(self, socket: Any, inbox: Inbox) -> None:
|
|
61
|
+
poller = self._zmq.Poller()
|
|
62
|
+
poller.register(socket, self._zmq.POLLIN)
|
|
63
|
+
try:
|
|
64
|
+
while not self._stop.is_set():
|
|
65
|
+
if dict(poller.poll(100)).get(socket):
|
|
66
|
+
inbox.put(json.loads(socket.recv_string()))
|
|
67
|
+
finally:
|
|
68
|
+
socket.close(linger=0)
|
capability/README.cn.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# capability/ — 进程可以加载的插件
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
这棵树是业务侧。内核启动进程并绑定它的资源记录。插件文件拥有卡片、工具参数和提示词文本。一个操作系统进程加载一个插件。模型和它调用的工具是对等进程,各自有自己的记录。
|
|
6
|
+
|
|
7
|
+
增加一个能力,就是增加一个本目录扫描能看见的文件。内核没有一份要去改的登记表。
|
|
8
|
+
|
|
9
|
+
[`process_adapter.py`](process_adapter.py) 随每次启动一起加载。`create_adapter()` 在已经加载的模块上找到 `load` 或 `load_async`,并转发一次请求。它只接受操作 `load`。卡片、消息形状和压缩选择留在插件里。
|
|
10
|
+
|
|
11
|
+
## 内核如何找到插件
|
|
12
|
+
|
|
13
|
+
[`kernel/process/process_creat`](../kernel/process/process_creat/README.cn.md) 里的 [`discover_instances`](../kernel/process/process_creat/instances.py) 遍历本目录。一个文件被登记,需要同时满足两条:
|
|
14
|
+
|
|
15
|
+
- 文件名以 `_plugin.py` 结尾。
|
|
16
|
+
- 文件文本里有 `def load(` 或 `async def load(`。
|
|
17
|
+
|
|
18
|
+
带了 `load` 函数的 `weather.py` 不会被看见。没有 `load` 函数的 `*_plugin.py` 也不会被看见。扫描读的是文本,不会为了判断而导入该文件。
|
|
19
|
+
|
|
20
|
+
能力名由路径算出来:
|
|
21
|
+
|
|
22
|
+
| 位置 | 名字 |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `capability/tools/.../glob_plugin.py` | `tools.glob` |
|
|
25
|
+
| `capability/model/.../openai_chat_model/*_plugin.py` | `model.openai_chat_model` |
|
|
26
|
+
| 嵌在 `capability/sandbox/` 下的插件 | `sandbox.sandbox` |
|
|
27
|
+
| `capability/<family>/.../thing_plugin.py` | `<family>.thing` |
|
|
28
|
+
|
|
29
|
+
`model` 用的是上一级目录名。`tools` 用的是去掉 `_plugin` 之后的文件名。直接放在 `capability/sandbox/` 里的插件会叫 `sandbox.<文件名>`;当前的入口是嵌套的,所以名字是 `sandbox.sandbox`。其他家族用第一级目录名和文件名。一个名字只保留一个文件。两个文件算出同一个名字时,留下排序后较后的那条路径。
|
|
30
|
+
|
|
31
|
+
`capability/prompt` 下名为 `prompt_main.py` 且定义了 `load` 的文件也会被登记,名字是 `prompt.<group>`。这棵树里没有这样的文件。
|
|
32
|
+
|
|
33
|
+
`linope process start <capability>` 启动一个已登记的名字。
|
|
34
|
+
|
|
35
|
+
## 可启动的插件要提供什么
|
|
36
|
+
|
|
37
|
+
[`kernel/process`](../kernel/process/README.cn.md) 的 `profile.py` 在打开记录之前调用 `capability_profile(capability_id, changes)`。该函数返回一份 `ProcessDeclaration`:能力名,以及它要租用的资源。种类是 `tool`、`sandbox`、`network` 和 `memory`。没有可用画像或画像失败时抛出 `ProfileUnavailable`,进程不会启动。卡片留在插件内部。
|
|
38
|
+
|
|
39
|
+
之后的请求调用 `load(kind, body, call_params=None)`。`kind` 是资源种类,例如 `tool`。`body` 是这次调用。`call_params` 是租约带进来的参数。异步插件再写一个参数相同的 `async def load_async(...)`。希望模型能看见的工具再提供 `tool_schemas()`。
|
|
40
|
+
|
|
41
|
+
工具的这份声明由 [`kernel/process/profiles.py`](../kernel/process/profiles.py) 里的 `tool_with_workspace` 和 `tool_only` 生成。哪些名字算只读、命令或写入,以及 `--change permission=` 和 `--change capabilities=` 如何选择模型能看见的工具,在 [`kernel/process`](../kernel/process/README.cn.md)。
|
|
42
|
+
|
|
43
|
+
## 目录
|
|
44
|
+
|
|
45
|
+
| 目录 | 职责 |
|
|
46
|
+
|---|---|
|
|
47
|
+
| [`model/`](model/README.cn.md) | 可启动的提供者插件,名字是 `model.<提供者目录>`。卡片、SDK 调用、消息块,以及加载一张点名卡片的运行时都在这里。回合在 [`kernel/scheduler`](../kernel/scheduler/README.cn.md)。 |
|
|
48
|
+
| [`tools/`](tools/README.cn.md) | 可启动的代理工具和外部宿主,名字是 `tools.<文件名>`:文件、shell、终端、代码、网页搜索、向用户提问,以及 MCP。`load` 接受种类 `tool`。 |
|
|
49
|
+
| [`sandbox/`](sandbox/README.cn.md) | 文件写入模式 `read-only`、`workspace-write`、`danger-full-access`,以及平台包装器。可启动的入口是 `sandbox.sandbox`。这里其余的 `*_plugin.py` 是 [`kernel/environment`](../kernel/environment/README.cn.md) 按路径加载的后端。Docker 工作区是另一份契约。 |
|
|
50
|
+
| [`context/`](context/README.cn.md) | 语义、摘要和滑动窗口压缩。每个包的入口文件叫 `capability_profile.py`,因此 `*_plugin.py` 的遍历不会登记它。`load` 在该文件夹里选出签名与正文相符的那一个函数。 |
|
|
51
|
+
| [`prompt/`](prompt/README.cn.md) | 系统提示词 Markdown。本目录没有 `load`。想使用这些文本的宿主自己读文件。 |
|
capability/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# capability/ — plugins a process can load
|
|
2
|
+
|
|
3
|
+
English | [中文](README.cn.md)
|
|
4
|
+
|
|
5
|
+
This tree is the business side. The kernel starts a process and binds its resource record. The plugin file owns the card, the tool arguments, and the prompt text. One operating-system process loads one plugin. A model and the tools it calls are peer processes, each with its own record.
|
|
6
|
+
|
|
7
|
+
Adding a capability is adding a file this tree's scan can see. The kernel has no registry to edit.
|
|
8
|
+
|
|
9
|
+
[`process_adapter.py`](process_adapter.py) is loaded with every start. `create_adapter()` finds `load` or `load_async` on the modules already loaded and forwards one request. The only operation it accepts is `load`. It leaves the card, the message shape, and the compression choice in the plugin.
|
|
10
|
+
|
|
11
|
+
## How the kernel finds a plugin
|
|
12
|
+
|
|
13
|
+
[`discover_instances`](../kernel/process/process_creat/instances.py) in [`kernel/process/process_creat`](../kernel/process/process_creat/README.md) walks this directory. A file is registered only when both are true:
|
|
14
|
+
|
|
15
|
+
- The file name ends with `_plugin.py`.
|
|
16
|
+
- The file text contains `def load(` or `async def load(`.
|
|
17
|
+
|
|
18
|
+
`weather.py` with a `load` function stays unseen. A `*_plugin.py` file with no `load` function stays unseen. The scan reads the text. It does not import the file to decide.
|
|
19
|
+
|
|
20
|
+
The capability name is computed from the path:
|
|
21
|
+
|
|
22
|
+
| Place | Name |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `capability/tools/.../glob_plugin.py` | `tools.glob` |
|
|
25
|
+
| `capability/model/.../openai_chat_model/*_plugin.py` | `model.openai_chat_model` |
|
|
26
|
+
| a plugin nested under `capability/sandbox/` | `sandbox.sandbox` |
|
|
27
|
+
| `capability/<family>/.../thing_plugin.py` | `<family>.thing` |
|
|
28
|
+
|
|
29
|
+
`model` uses the parent directory name. `tools` uses the file name with `_plugin` removed. A plugin sitting directly in `capability/sandbox/` would be `sandbox.<file stem>`; the current entry is nested, so its name is `sandbox.sandbox`. Any other family uses its first directory and the file name. One name keeps one file. Two files that compute the same name leave the later path in sorted order.
|
|
30
|
+
|
|
31
|
+
A file named `prompt_main.py` under `capability/prompt` is also registered, as `prompt.<group>`, when it defines `load`. This tree has no such file.
|
|
32
|
+
|
|
33
|
+
`linope process start <capability>` starts one registered name.
|
|
34
|
+
|
|
35
|
+
## What a startable plugin provides
|
|
36
|
+
|
|
37
|
+
[`kernel/process`](../kernel/process/README.md) `profile.py` calls `capability_profile(capability_id, changes)` before the record is opened. The function returns a `ProcessDeclaration`: the capability name and the resources it leases. The kinds are `tool`, `sandbox`, `network`, and `memory`. A missing or failing profile raises `ProfileUnavailable`, and the process does not start. The card stays inside the plugin.
|
|
38
|
+
|
|
39
|
+
A later request calls `load(kind, body, call_params=None)`. `kind` is the resource kind, such as `tool`. `body` is the call. `call_params` is what the lease carried in. An async plugin adds `async def load_async(...)` with the same arguments. A tool the model should be offered also exposes `tool_schemas()`.
|
|
40
|
+
|
|
41
|
+
`tool_with_workspace` and `tool_only` in [`kernel/process/profiles.py`](../kernel/process/profiles.py) build that declaration for a tool. Which names count as read, command, or write, and how `--change permission=` and `--change capabilities=` choose the tools a model sees, is [`kernel/process`](../kernel/process/README.md).
|
|
42
|
+
|
|
43
|
+
## Directories
|
|
44
|
+
|
|
45
|
+
| Directory | Role |
|
|
46
|
+
|---|---|
|
|
47
|
+
| [`model/`](model/README.md) | Startable provider plugins, named `model.<provider directory>`. The card, the SDK call, the message blocks, and the runtime that loads a named card live here. The turn is [`kernel/scheduler`](../kernel/scheduler/README.md). |
|
|
48
|
+
| [`tools/`](tools/README.md) | Startable agent tools and external hosts, named `tools.<file stem>`: files, shell, terminal, code, web search, questions, and MCP. `load` accepts kind `tool`. |
|
|
49
|
+
| [`sandbox/`](sandbox/README.md) | File-write modes `read-only`, `workspace-write`, and `danger-full-access`, plus the platform wrappers. The startable entry is `sandbox.sandbox`. Other `*_plugin.py` files here are backends [`kernel/environment`](../kernel/environment/README.md) loads by path. The Docker workspace is a separate contract. |
|
|
50
|
+
| [`context/`](context/README.md) | Semantic, summary, and sliding-window compression. Each package's entry is `capability_profile.py`, so the `*_plugin.py` walk does not register it. `load` picks the one function in the folder whose signature fits the body. |
|
|
51
|
+
| [`prompt/`](prompt/README.md) | System-prompt markdown. This directory has no `load`. A host that wants the text reads the files itself. |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# context/ — 进程可以加载的压缩函数
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
`load_in_directory` 在一个文件夹里选出签名恰好接受正文字段、且不多接受字段的那一个公开函数。零个匹配或多于一个匹配抛出 `ValueError`。`capability_profile` 和 `load` 不是候选。字符串正文变成一条用户消息。
|
|
6
|
+
|
|
7
|
+
每个压缩包声明一份 `memory` 资源,其 `scope` 是能力 id。`--change` 的值不会应用到该声明上。
|
|
8
|
+
|
|
9
|
+
| 目录 | 职责 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| [`context_compression/`](context_compression/README.cn.md) | 语义、摘要和滑动窗口函数 |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# context/ — compression functions a process can load
|
|
2
|
+
|
|
3
|
+
English | [中文](README.cn.md)
|
|
4
|
+
|
|
5
|
+
`load_in_directory` picks the one public function in a folder whose signature accepts the body's keys and no extra keys. Zero matches or more than one match raises `ValueError`. `capability_profile` and `load` are not candidates. A string body becomes one user message.
|
|
6
|
+
|
|
7
|
+
Each compression package claims a `memory` resource whose `scope` is the capability id. `--change` values are not applied to that declaration.
|
|
8
|
+
|
|
9
|
+
| Directory | Role |
|
|
10
|
+
|---|---|
|
|
11
|
+
| [`context_compression/`](context_compression/README.md) | Semantic, summary, and sliding-window functions |
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Context capability package. Its load chooses the compression function."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib.util
|
|
6
|
+
import inspect
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def load_in_directory(directory: Path, kind: str, body: Any) -> Any:
|
|
13
|
+
"""Load context content with the one function in this folder that fits."""
|
|
14
|
+
if kind != "context":
|
|
15
|
+
raise ValueError(f"This process cannot load {kind}")
|
|
16
|
+
arguments = _arguments(body)
|
|
17
|
+
matches = _functions_for_arguments(directory, arguments)
|
|
18
|
+
if len(matches) != 1:
|
|
19
|
+
raise ValueError(
|
|
20
|
+
"No function can load this content" if not matches else "More than one function matches this content"
|
|
21
|
+
)
|
|
22
|
+
return _invoke(matches[0], arguments)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _arguments(body: Any) -> dict[str, Any]:
|
|
26
|
+
if isinstance(body, dict):
|
|
27
|
+
return body
|
|
28
|
+
if isinstance(body, str):
|
|
29
|
+
return {"messages": [{"role": "user", "content": body}]}
|
|
30
|
+
raise TypeError("context content must be a mapping or text")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _functions_for_arguments(directory: Path, arguments: dict[str, Any]) -> list[Any]:
|
|
34
|
+
keys = set(arguments)
|
|
35
|
+
found: list[Any] = []
|
|
36
|
+
seen: set[int] = set()
|
|
37
|
+
for path in sorted(directory.glob("*.py")):
|
|
38
|
+
if path.name.startswith("test_") or path.name == "__init__.py":
|
|
39
|
+
continue
|
|
40
|
+
module = _load(path)
|
|
41
|
+
for name, value in vars(module).items():
|
|
42
|
+
if not _is_local_function(name, value, directory) or id(value) in seen:
|
|
43
|
+
continue
|
|
44
|
+
if not _accepts_arguments(value, keys):
|
|
45
|
+
continue
|
|
46
|
+
seen.add(id(value))
|
|
47
|
+
found.append(value)
|
|
48
|
+
return found
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _is_local_function(name: str, value: Any, directory: Path) -> bool:
|
|
52
|
+
if not inspect.isfunction(value) or name.startswith("_") or name in {
|
|
53
|
+
"capability_profile",
|
|
54
|
+
"load",
|
|
55
|
+
}:
|
|
56
|
+
return False
|
|
57
|
+
code = getattr(value, "__code__", None)
|
|
58
|
+
if code is None:
|
|
59
|
+
return False
|
|
60
|
+
return Path(code.co_filename).resolve().parent == directory.resolve()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _accepts_arguments(function: Any, keys: set[str]) -> bool:
|
|
64
|
+
try:
|
|
65
|
+
signature = inspect.signature(function)
|
|
66
|
+
except (TypeError, ValueError):
|
|
67
|
+
return False
|
|
68
|
+
required: set[str] = set()
|
|
69
|
+
accepted: set[str] = set()
|
|
70
|
+
for parameter in signature.parameters.values():
|
|
71
|
+
if parameter.kind in {
|
|
72
|
+
inspect.Parameter.VAR_POSITIONAL,
|
|
73
|
+
inspect.Parameter.VAR_KEYWORD,
|
|
74
|
+
}:
|
|
75
|
+
continue
|
|
76
|
+
accepted.add(parameter.name)
|
|
77
|
+
if parameter.default is inspect.Parameter.empty:
|
|
78
|
+
required.add(parameter.name)
|
|
79
|
+
return required <= keys <= accepted
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _invoke(function: Any, arguments: dict[str, Any]) -> Any:
|
|
83
|
+
try:
|
|
84
|
+
bound = inspect.signature(function).bind(**arguments)
|
|
85
|
+
except TypeError as error:
|
|
86
|
+
raise TypeError(f"Cannot load content: {error}") from error
|
|
87
|
+
bound.apply_defaults()
|
|
88
|
+
if inspect.iscoroutinefunction(function):
|
|
89
|
+
return __import__("asyncio").run(function(*bound.args, **bound.kwargs))
|
|
90
|
+
return function(*bound.args, **bound.kwargs)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _load(path: Path) -> Any:
|
|
94
|
+
resolved = path.resolve()
|
|
95
|
+
for module in list(sys.modules.values()):
|
|
96
|
+
raw = getattr(module, "__file__", None)
|
|
97
|
+
if raw and Path(raw).resolve() == resolved:
|
|
98
|
+
return module
|
|
99
|
+
token = "".join(character if character.isalnum() else "_" for character in resolved.as_posix())
|
|
100
|
+
name = "context_capability_" + token[-80:]
|
|
101
|
+
spec = importlib.util.spec_from_file_location(name, resolved)
|
|
102
|
+
if spec is None or spec.loader is None:
|
|
103
|
+
raise ImportError(resolved)
|
|
104
|
+
module = importlib.util.module_from_spec(spec)
|
|
105
|
+
sys.modules[name] = module
|
|
106
|
+
spec.loader.exec_module(module)
|
|
107
|
+
return module
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# context_compression/ — 三个压缩包
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
每个包由自己的 `load` 加载,它对那个包的文件夹调用 [`load_in_directory`](../README.cn.md)。一个包里的函数不导入另一个包。token 计数由调用方注入。本目录不发现一条唯一的流水线。
|
|
6
|
+
|
|
7
|
+
| 目录 | 职责 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| [`semantic_compression/`](semantic_compression/README.cn.md) | 对工具结果、参数和媒体的确定性改写 |
|
|
10
|
+
| [`summary_compression/`](summary_compression/README.cn.md) | 摘要预算、提示词、模型调用和转录组装 |
|
|
11
|
+
| [`sliding_window/`](sliding_window/README.cn.md) | 头部保护、锚点,以及尾部裁剪 |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# context_compression/ — three compression packages
|
|
2
|
+
|
|
3
|
+
English | [中文](README.cn.md)
|
|
4
|
+
|
|
5
|
+
Each package is loaded by its own `load`, which calls [`load_in_directory`](../README.md) on that package's folder. Functions in one package do not import another package. Token counting is injected by the caller. This directory does not discover a single pipeline.
|
|
6
|
+
|
|
7
|
+
| Directory | Role |
|
|
8
|
+
|---|---|
|
|
9
|
+
| [`semantic_compression/`](semantic_compression/README.md) | Deterministic rewrites of tool results, arguments, and media |
|
|
10
|
+
| [`summary_compression/`](summary_compression/README.md) | Summary budget, prompt, model call, and transcript assembly |
|
|
11
|
+
| [`sliding_window/`](sliding_window/README.md) | Head protection, anchors, and a tail cut |
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# 语义压缩的原子函数
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
对 `list[dict]` 消息的小型确定性函数。`load` 通过 [`load_in_directory`](../../README.cn.md) 选出其中一个。宿主也可以导入这些函数并传入回调。没有函数导入本目录里的另一个模块、`sliding_window` 或 `summary_compression`。
|
|
6
|
+
|
|
7
|
+
## 契约
|
|
8
|
+
|
|
9
|
+
- 消息变换接受并返回 `list[dict]`。
|
|
10
|
+
- 没有函数导入另一个项目模块,或本目录里的另一个函数。
|
|
11
|
+
- 没有函数导入 `sliding_window` 或 `summary_compression`。
|
|
12
|
+
- 这里不实现 token 计数。宿主注入 `estimate_messages(list[dict]) -> int`。
|
|
13
|
+
- 摘要、标记、选择规则和策略决定可以注入。
|
|
14
|
+
- 空操作通常返回原来的列表对象,让宿主能用身份判断是否提交了改写。
|
|
15
|
+
- 函数只浅复制被改写的消息或调用,不修改输入。
|
|
16
|
+
|
|
17
|
+
## 原子函数
|
|
18
|
+
|
|
19
|
+
- `tool_result_dedup.py`:保留相同字符串工具结果的最新完整副本,并把更早的副本换成回指。
|
|
20
|
+
- `tool_result_summary.py`:常见工具的安全一行摘要,加上永不抛出的回退;也暴露由回调驱动的结果替换。
|
|
21
|
+
- `json_args_truncation.py`:解析 JSON 之后递归截断字符串叶子,保留合法 JSON,畸形参数保持不变。
|
|
22
|
+
- `old_tool_result_demotion.py`:用注入的摘要、图片和保护回调,降级宿主选出的旧结果。
|
|
23
|
+
- `protected_tail_pressure.py`:降级受保护尾部的结果,直到注入的估计器报告尾部低于其软上限。
|
|
24
|
+
- `proactive_prune_gate.py`:在提交会打破提示缓存的主动修剪之前,应用触发、资格和测得回收量这些门。
|
|
25
|
+
- `tool_pair_sanitizer.py`:去掉孤儿工具结果,并剥掉没有匹配结果的工具调用。
|
|
26
|
+
- `media_stripping.py`:替换图片部分,并剥掉比最新一条带图片的用户消息更早的图片。
|
|
27
|
+
- `skill_view_guard.py`:识别 `skill_view` 调用,计算受保护的技能名,创建降级保护回调,并收集幽灵标记。
|
|
28
|
+
- `deterministic_pipeline.py`:可选的、只跑回调的多遍运行器。它不导入插件,也不包含策略。
|
|
29
|
+
|
|
30
|
+
## 宿主组合
|
|
31
|
+
|
|
32
|
+
宿主拥有配置,并导入它想要的函数。它为边界和策略创建闭包,然后按这个顺序传给只跑回调的流水线:
|
|
33
|
+
|
|
34
|
+
1. 去重工具结果。
|
|
35
|
+
2. 计算受保护尾部的边界。
|
|
36
|
+
3. 从原始或当前消息建立 `skill_view` 保护。
|
|
37
|
+
4. 降级边界以外的旧工具结果。
|
|
38
|
+
5. 截断旧的 JSON 工具参数。
|
|
39
|
+
6. 用宿主估计器做受保护尾部的压力降级。
|
|
40
|
+
7. 清理工具调用和结果对。
|
|
41
|
+
8. 剥掉历史媒体。
|
|
42
|
+
9. 在语义摘要之前收集幽灵技能标记,并把缺失的标记注入宿主产生的摘要。
|
|
43
|
+
|
|
44
|
+
主动路径应把第 1、4、5 步作为候选放进 `commit_proactive_prune`。那个插件估计实际的前后列表,除非达到回收阈值,否则返回原来的对象。
|
|
45
|
+
|
|
46
|
+
宿主接线示例(仅作说明):
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
passes = [
|
|
50
|
+
deduplicate_tool_results,
|
|
51
|
+
lambda rows: demote_old_tool_results(
|
|
52
|
+
rows,
|
|
53
|
+
should_demote=lambda index, _row: index < protected_start,
|
|
54
|
+
summary_callback=default_tool_result_summary,
|
|
55
|
+
protect_callback=skill_protection,
|
|
56
|
+
),
|
|
57
|
+
lambda rows: truncate_tool_call_arguments(
|
|
58
|
+
rows,
|
|
59
|
+
should_truncate=lambda index, _row: index < protected_start,
|
|
60
|
+
),
|
|
61
|
+
lambda rows: demote_protected_tail_under_pressure(
|
|
62
|
+
rows,
|
|
63
|
+
protected_start=protected_start,
|
|
64
|
+
soft_token_limit=tail_limit,
|
|
65
|
+
estimate_messages=host_estimator,
|
|
66
|
+
summary_callback=default_tool_result_summary,
|
|
67
|
+
),
|
|
68
|
+
sanitize_tool_pairs,
|
|
69
|
+
strip_historical_media,
|
|
70
|
+
]
|
|
71
|
+
compressed = run_deterministic_pipeline(messages, passes=passes)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
这个示例里的名字故意不通过 `__init__`、门面或宿主模块重新导出。宿主直接导入每个原子插件。
|
|
75
|
+
|
|
76
|
+
## 已知限制与暂缓事项
|
|
77
|
+
|
|
78
|
+
- **没有登记流水线** — `deterministic_pipeline.py` 运行给它的回调,不导入兄弟。本包上的 `load` 仍按参数名选出一个函数。
|
|
79
|
+
- **token 计数是注入的** — 宿主传入时,函数调用 `estimate_messages`。本目录自己不计数。
|