jarvis-ai-assistant 0.7.8__py3-none-any.whl → 1.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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +567 -222
- jarvis/jarvis_agent/agent_manager.py +19 -12
- jarvis/jarvis_agent/builtin_input_handler.py +79 -11
- jarvis/jarvis_agent/config_editor.py +7 -2
- jarvis/jarvis_agent/event_bus.py +24 -13
- jarvis/jarvis_agent/events.py +19 -1
- jarvis/jarvis_agent/file_context_handler.py +67 -64
- jarvis/jarvis_agent/file_methodology_manager.py +38 -24
- jarvis/jarvis_agent/jarvis.py +186 -114
- jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
- jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
- jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
- jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
- jarvis/jarvis_agent/language_support_info.py +250 -219
- jarvis/jarvis_agent/main.py +19 -23
- jarvis/jarvis_agent/memory_manager.py +9 -6
- jarvis/jarvis_agent/methodology_share_manager.py +21 -15
- jarvis/jarvis_agent/output_handler.py +4 -2
- jarvis/jarvis_agent/prompt_builder.py +7 -6
- jarvis/jarvis_agent/prompt_manager.py +113 -8
- jarvis/jarvis_agent/prompts.py +317 -85
- jarvis/jarvis_agent/protocols.py +5 -2
- jarvis/jarvis_agent/run_loop.py +192 -32
- jarvis/jarvis_agent/session_manager.py +7 -3
- jarvis/jarvis_agent/share_manager.py +23 -13
- jarvis/jarvis_agent/shell_input_handler.py +12 -8
- jarvis/jarvis_agent/stdio_redirect.py +25 -26
- jarvis/jarvis_agent/task_analyzer.py +29 -23
- jarvis/jarvis_agent/task_list.py +869 -0
- jarvis/jarvis_agent/task_manager.py +26 -23
- jarvis/jarvis_agent/tool_executor.py +6 -5
- jarvis/jarvis_agent/tool_share_manager.py +24 -14
- jarvis/jarvis_agent/user_interaction.py +3 -3
- jarvis/jarvis_agent/utils.py +9 -1
- jarvis/jarvis_agent/web_bridge.py +37 -17
- jarvis/jarvis_agent/web_output_sink.py +5 -2
- jarvis/jarvis_agent/web_server.py +165 -36
- jarvis/jarvis_c2rust/__init__.py +1 -1
- jarvis/jarvis_c2rust/cli.py +260 -141
- jarvis/jarvis_c2rust/collector.py +37 -18
- jarvis/jarvis_c2rust/constants.py +60 -0
- jarvis/jarvis_c2rust/library_replacer.py +242 -1010
- jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
- jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
- jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
- jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
- jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
- jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
- jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
- jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
- jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
- jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
- jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
- jarvis/jarvis_c2rust/loaders.py +28 -10
- jarvis/jarvis_c2rust/models.py +5 -2
- jarvis/jarvis_c2rust/optimizer.py +192 -1974
- jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
- jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
- jarvis/jarvis_c2rust/optimizer_config.py +49 -0
- jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
- jarvis/jarvis_c2rust/optimizer_options.py +48 -0
- jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
- jarvis/jarvis_c2rust/optimizer_report.py +52 -0
- jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
- jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
- jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
- jarvis/jarvis_c2rust/scanner.py +229 -166
- jarvis/jarvis_c2rust/transpiler.py +531 -2732
- jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
- jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
- jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
- jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
- jarvis/jarvis_c2rust/transpiler_config.py +178 -0
- jarvis/jarvis_c2rust/transpiler_context.py +122 -0
- jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
- jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
- jarvis/jarvis_c2rust/transpiler_git.py +163 -0
- jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
- jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
- jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
- jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
- jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
- jarvis/jarvis_c2rust/utils.py +269 -79
- jarvis/jarvis_code_agent/after_change.py +233 -0
- jarvis/jarvis_code_agent/build_validation_config.py +37 -30
- jarvis/jarvis_code_agent/builtin_rules.py +68 -0
- jarvis/jarvis_code_agent/code_agent.py +976 -1517
- jarvis/jarvis_code_agent/code_agent_build.py +227 -0
- jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
- jarvis/jarvis_code_agent/code_agent_git.py +525 -0
- jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
- jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
- jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
- jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
- jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
- jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
- jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
- jarvis/jarvis_code_agent/lint.py +223 -524
- jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
- jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
- jarvis/jarvis_code_agent/rules/code_review.md +115 -0
- jarvis/jarvis_code_agent/rules/documentation.md +165 -0
- jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
- jarvis/jarvis_code_agent/rules/performance.md +158 -0
- jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
- jarvis/jarvis_code_agent/rules/security.md +160 -0
- jarvis/jarvis_code_agent/rules/tdd.md +78 -0
- jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
- jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
- jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
- jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
- jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
- jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
- jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
- jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
- jarvis/jarvis_code_agent/utils.py +36 -26
- jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
- jarvis/jarvis_code_analysis/code_review.py +64 -33
- jarvis/jarvis_data/config_schema.json +285 -192
- jarvis/jarvis_git_squash/main.py +8 -6
- jarvis/jarvis_git_utils/git_commiter.py +53 -76
- jarvis/jarvis_mcp/__init__.py +5 -2
- jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
- jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
- jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
- jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
- jarvis/jarvis_methodology/main.py +48 -39
- jarvis/jarvis_multi_agent/__init__.py +56 -23
- jarvis/jarvis_multi_agent/main.py +15 -18
- jarvis/jarvis_platform/base.py +179 -111
- jarvis/jarvis_platform/human.py +27 -16
- jarvis/jarvis_platform/kimi.py +52 -45
- jarvis/jarvis_platform/openai.py +101 -40
- jarvis/jarvis_platform/registry.py +51 -33
- jarvis/jarvis_platform/tongyi.py +68 -38
- jarvis/jarvis_platform/yuanbao.py +59 -43
- jarvis/jarvis_platform_manager/main.py +68 -76
- jarvis/jarvis_platform_manager/service.py +24 -14
- jarvis/jarvis_rag/README_CONFIG.md +314 -0
- jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
- jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
- jarvis/jarvis_rag/__init__.py +57 -4
- jarvis/jarvis_rag/cache.py +3 -1
- jarvis/jarvis_rag/cli.py +48 -68
- jarvis/jarvis_rag/embedding_interface.py +39 -0
- jarvis/jarvis_rag/embedding_manager.py +7 -230
- jarvis/jarvis_rag/embeddings/__init__.py +41 -0
- jarvis/jarvis_rag/embeddings/base.py +114 -0
- jarvis/jarvis_rag/embeddings/cohere.py +66 -0
- jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
- jarvis/jarvis_rag/embeddings/local.py +260 -0
- jarvis/jarvis_rag/embeddings/openai.py +62 -0
- jarvis/jarvis_rag/embeddings/registry.py +293 -0
- jarvis/jarvis_rag/llm_interface.py +8 -6
- jarvis/jarvis_rag/query_rewriter.py +8 -9
- jarvis/jarvis_rag/rag_pipeline.py +61 -52
- jarvis/jarvis_rag/reranker.py +7 -75
- jarvis/jarvis_rag/reranker_interface.py +32 -0
- jarvis/jarvis_rag/rerankers/__init__.py +41 -0
- jarvis/jarvis_rag/rerankers/base.py +109 -0
- jarvis/jarvis_rag/rerankers/cohere.py +67 -0
- jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
- jarvis/jarvis_rag/rerankers/jina.py +79 -0
- jarvis/jarvis_rag/rerankers/local.py +89 -0
- jarvis/jarvis_rag/rerankers/registry.py +293 -0
- jarvis/jarvis_rag/retriever.py +58 -43
- jarvis/jarvis_sec/__init__.py +66 -141
- jarvis/jarvis_sec/agents.py +21 -17
- jarvis/jarvis_sec/analysis.py +80 -33
- jarvis/jarvis_sec/checkers/__init__.py +7 -13
- jarvis/jarvis_sec/checkers/c_checker.py +356 -164
- jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
- jarvis/jarvis_sec/cli.py +43 -21
- jarvis/jarvis_sec/clustering.py +430 -272
- jarvis/jarvis_sec/file_manager.py +99 -55
- jarvis/jarvis_sec/parsers.py +9 -6
- jarvis/jarvis_sec/prompts.py +4 -3
- jarvis/jarvis_sec/report.py +44 -22
- jarvis/jarvis_sec/review.py +180 -107
- jarvis/jarvis_sec/status.py +50 -41
- jarvis/jarvis_sec/types.py +3 -0
- jarvis/jarvis_sec/utils.py +160 -83
- jarvis/jarvis_sec/verification.py +411 -181
- jarvis/jarvis_sec/workflow.py +132 -21
- jarvis/jarvis_smart_shell/main.py +28 -41
- jarvis/jarvis_stats/cli.py +14 -12
- jarvis/jarvis_stats/stats.py +28 -19
- jarvis/jarvis_stats/storage.py +14 -8
- jarvis/jarvis_stats/visualizer.py +12 -7
- jarvis/jarvis_tools/base.py +5 -2
- jarvis/jarvis_tools/clear_memory.py +13 -9
- jarvis/jarvis_tools/cli/main.py +23 -18
- jarvis/jarvis_tools/edit_file.py +572 -873
- jarvis/jarvis_tools/execute_script.py +10 -7
- jarvis/jarvis_tools/file_analyzer.py +7 -8
- jarvis/jarvis_tools/meta_agent.py +287 -0
- jarvis/jarvis_tools/methodology.py +5 -3
- jarvis/jarvis_tools/read_code.py +305 -1438
- jarvis/jarvis_tools/read_symbols.py +50 -17
- jarvis/jarvis_tools/read_webpage.py +19 -18
- jarvis/jarvis_tools/registry.py +435 -156
- jarvis/jarvis_tools/retrieve_memory.py +16 -11
- jarvis/jarvis_tools/save_memory.py +8 -6
- jarvis/jarvis_tools/search_web.py +31 -31
- jarvis/jarvis_tools/sub_agent.py +32 -28
- jarvis/jarvis_tools/sub_code_agent.py +44 -60
- jarvis/jarvis_tools/task_list_manager.py +1811 -0
- jarvis/jarvis_tools/virtual_tty.py +29 -19
- jarvis/jarvis_utils/__init__.py +4 -0
- jarvis/jarvis_utils/builtin_replace_map.py +2 -1
- jarvis/jarvis_utils/clipboard.py +9 -8
- jarvis/jarvis_utils/collections.py +331 -0
- jarvis/jarvis_utils/config.py +699 -194
- jarvis/jarvis_utils/dialogue_recorder.py +294 -0
- jarvis/jarvis_utils/embedding.py +6 -3
- jarvis/jarvis_utils/file_processors.py +7 -1
- jarvis/jarvis_utils/fzf.py +9 -3
- jarvis/jarvis_utils/git_utils.py +71 -42
- jarvis/jarvis_utils/globals.py +116 -32
- jarvis/jarvis_utils/http.py +6 -2
- jarvis/jarvis_utils/input.py +318 -83
- jarvis/jarvis_utils/jsonnet_compat.py +119 -104
- jarvis/jarvis_utils/methodology.py +37 -28
- jarvis/jarvis_utils/output.py +201 -44
- jarvis/jarvis_utils/utils.py +986 -628
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
- jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
- jarvis/jarvis_tools/generate_new_tool.py +0 -205
- jarvis/jarvis_tools/lsp_client.py +0 -1552
- jarvis/jarvis_tools/rewrite_file.py +0 -105
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -10,23 +10,27 @@
|
|
|
10
10
|
- 注入 web_multiline_input 与 web_user_confirm 到 Agent,使输入与确认经由浏览器完成
|
|
11
11
|
- 启动本服务,前端通过页面与 Agent 交互
|
|
12
12
|
"""
|
|
13
|
+
|
|
13
14
|
from __future__ import annotations
|
|
14
15
|
|
|
16
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
17
|
+
|
|
15
18
|
import asyncio
|
|
19
|
+
import atexit
|
|
16
20
|
import json
|
|
17
21
|
import os
|
|
18
22
|
import signal
|
|
19
|
-
import atexit
|
|
20
23
|
from pathlib import Path
|
|
21
|
-
from typing import Any, Dict,
|
|
24
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
22
25
|
|
|
23
26
|
import uvicorn
|
|
24
27
|
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
25
|
-
from fastapi.responses import HTMLResponse
|
|
26
28
|
from fastapi.middleware.cors import CORSMiddleware
|
|
29
|
+
from fastapi.responses import HTMLResponse
|
|
27
30
|
|
|
28
31
|
from jarvis.jarvis_agent.web_bridge import WebBridge
|
|
29
|
-
from jarvis.jarvis_utils.globals import
|
|
32
|
+
from jarvis.jarvis_utils.globals import console, set_interrupt
|
|
33
|
+
|
|
30
34
|
|
|
31
35
|
# ---------------------------
|
|
32
36
|
# 应用与页面
|
|
@@ -245,10 +249,13 @@ writeLine('消息解析失败: ' + e);
|
|
|
245
249
|
|
|
246
250
|
return app
|
|
247
251
|
|
|
252
|
+
|
|
248
253
|
# ---------------------------
|
|
249
254
|
# WebSocket 端点
|
|
250
255
|
# ---------------------------
|
|
251
|
-
async def _ws_sender_loop(
|
|
256
|
+
async def _ws_sender_loop(
|
|
257
|
+
ws: WebSocket, queue: "asyncio.Queue[Dict[str, Any]]"
|
|
258
|
+
) -> None:
|
|
252
259
|
try:
|
|
253
260
|
while True:
|
|
254
261
|
payload = await queue.get()
|
|
@@ -257,20 +264,28 @@ async def _ws_sender_loop(ws: WebSocket, queue: "asyncio.Queue[Dict[str, Any]]")
|
|
|
257
264
|
# 发送循环异常即退出
|
|
258
265
|
pass
|
|
259
266
|
|
|
260
|
-
|
|
267
|
+
|
|
268
|
+
def _make_sender(
|
|
269
|
+
queue: "asyncio.Queue[Dict[str, Any]]",
|
|
270
|
+
) -> Callable[[Dict[str, Any]], None]:
|
|
261
271
|
# 同步函数,供 WebBridge 注册;将消息放入异步队列,由协程发送
|
|
262
272
|
def _sender(payload: Dict[str, Any]) -> None:
|
|
263
273
|
try:
|
|
264
274
|
queue.put_nowait(payload)
|
|
265
275
|
except Exception:
|
|
266
276
|
pass
|
|
277
|
+
|
|
267
278
|
return _sender
|
|
268
279
|
|
|
269
|
-
|
|
280
|
+
|
|
281
|
+
def _make_sender_filtered(
|
|
282
|
+
queue: "asyncio.Queue[Dict[str, Any]]", allowed_types: Optional[list[str]] = None
|
|
283
|
+
) -> Callable[[Dict[str, Any]], None]:
|
|
270
284
|
"""
|
|
271
285
|
过滤版 sender:仅将指定类型的payload放入队列(用于单独的STDIO通道)。
|
|
272
286
|
"""
|
|
273
287
|
allowed = set(allowed_types or [])
|
|
288
|
+
|
|
274
289
|
def _sender(payload: Dict[str, Any]) -> None:
|
|
275
290
|
try:
|
|
276
291
|
ptype = payload.get("type")
|
|
@@ -278,8 +293,10 @@ def _make_sender_filtered(queue: "asyncio.Queue[Dict[str, Any]]", allowed_types:
|
|
|
278
293
|
queue.put_nowait(payload)
|
|
279
294
|
except Exception:
|
|
280
295
|
pass
|
|
296
|
+
|
|
281
297
|
return _sender
|
|
282
298
|
|
|
299
|
+
|
|
283
300
|
def _run_and_notify(agent: Any, text: str) -> None:
|
|
284
301
|
try:
|
|
285
302
|
agent.run(text)
|
|
@@ -289,14 +306,20 @@ def _run_and_notify(agent: Any, text: str) -> None:
|
|
|
289
306
|
except Exception:
|
|
290
307
|
pass
|
|
291
308
|
|
|
292
|
-
|
|
309
|
+
|
|
310
|
+
def start_web_server(
|
|
311
|
+
agent: Any,
|
|
312
|
+
host: str = "127.0.0.1",
|
|
313
|
+
port: int = 8765,
|
|
314
|
+
launch_command: Optional[List[str]] = None,
|
|
315
|
+
) -> None:
|
|
293
316
|
"""
|
|
294
317
|
启动Web服务,并将Agent绑定到应用上下文。
|
|
295
318
|
- agent: 现有的 Agent 实例(已完成初始化)
|
|
296
319
|
- host: Web 服务主机地址
|
|
297
320
|
- port: Web 服务端口
|
|
298
321
|
- launch_command: 交互式终端启动命令(列表格式,如 ["jvs", "--task", "xxx"]),
|
|
299
|
-
如果为 None,则从环境变量
|
|
322
|
+
如果为 None,则从环境变量 web_launch_json 读取
|
|
300
323
|
"""
|
|
301
324
|
app = _build_app()
|
|
302
325
|
app.state.agent = agent # 供 WS 端点调用
|
|
@@ -319,7 +342,14 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
319
342
|
bridge.add_client(sender)
|
|
320
343
|
send_task = asyncio.create_task(_ws_sender_loop(ws, queue))
|
|
321
344
|
try:
|
|
322
|
-
await ws.send_text(
|
|
345
|
+
await ws.send_text(
|
|
346
|
+
json.dumps(
|
|
347
|
+
{
|
|
348
|
+
"type": "output",
|
|
349
|
+
"payload": {"text": "STDIO 通道已就绪", "output_type": "INFO"},
|
|
350
|
+
}
|
|
351
|
+
)
|
|
352
|
+
)
|
|
323
353
|
except Exception:
|
|
324
354
|
pass
|
|
325
355
|
try:
|
|
@@ -334,6 +364,7 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
334
364
|
if mtype == "stdin":
|
|
335
365
|
try:
|
|
336
366
|
from jarvis.jarvis_agent.stdio_redirect import feed_web_stdin
|
|
367
|
+
|
|
337
368
|
text = data.get("data", "")
|
|
338
369
|
if isinstance(text, str) and text:
|
|
339
370
|
feed_web_stdin(text)
|
|
@@ -372,7 +403,9 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
372
403
|
try:
|
|
373
404
|
set_interrupt(True)
|
|
374
405
|
# 可选:发送回执
|
|
375
|
-
await ws.send_text(
|
|
406
|
+
await ws.send_text(
|
|
407
|
+
json.dumps({"type": "ack", "cmd": "interrupt"})
|
|
408
|
+
)
|
|
376
409
|
except Exception:
|
|
377
410
|
pass
|
|
378
411
|
elif mtype == "resize":
|
|
@@ -411,9 +444,20 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
411
444
|
await ws.accept()
|
|
412
445
|
# 仅在非 Windows 平台提供 PTY 功能
|
|
413
446
|
import sys as _sys
|
|
447
|
+
|
|
414
448
|
if _sys.platform == "win32":
|
|
415
449
|
try:
|
|
416
|
-
await ws.send_text(
|
|
450
|
+
await ws.send_text(
|
|
451
|
+
json.dumps(
|
|
452
|
+
{
|
|
453
|
+
"type": "output",
|
|
454
|
+
"payload": {
|
|
455
|
+
"text": "当前平台不支持交互式终端(PTY)",
|
|
456
|
+
"output_type": "ERROR",
|
|
457
|
+
},
|
|
458
|
+
}
|
|
459
|
+
)
|
|
460
|
+
)
|
|
417
461
|
except Exception:
|
|
418
462
|
pass
|
|
419
463
|
try:
|
|
@@ -423,15 +467,26 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
423
467
|
return
|
|
424
468
|
|
|
425
469
|
import os as _os
|
|
470
|
+
|
|
426
471
|
try:
|
|
427
|
-
import pty as _pty
|
|
428
472
|
import fcntl as _fcntl
|
|
473
|
+
import pty as _pty
|
|
429
474
|
import select as _select
|
|
430
|
-
import termios as _termios
|
|
431
475
|
import struct as _struct
|
|
476
|
+
import termios as _termios
|
|
432
477
|
except Exception:
|
|
433
478
|
try:
|
|
434
|
-
await ws.send_text(
|
|
479
|
+
await ws.send_text(
|
|
480
|
+
json.dumps(
|
|
481
|
+
{
|
|
482
|
+
"type": "output",
|
|
483
|
+
"payload": {
|
|
484
|
+
"text": "服务端缺少 PTY 相关依赖,无法启动交互式终端",
|
|
485
|
+
"output_type": "ERROR",
|
|
486
|
+
},
|
|
487
|
+
}
|
|
488
|
+
)
|
|
489
|
+
)
|
|
435
490
|
except Exception:
|
|
436
491
|
pass
|
|
437
492
|
try:
|
|
@@ -456,24 +511,29 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
456
511
|
# 会话结束后等待用户按回车再重启
|
|
457
512
|
waiting_for_ack = False
|
|
458
513
|
ack_event = asyncio.Event()
|
|
459
|
-
|
|
514
|
+
|
|
460
515
|
# 在 fork 前获取启动命令(避免在子进程中访问 app.state)
|
|
461
516
|
_launch_cmd = None
|
|
462
517
|
try:
|
|
463
518
|
if hasattr(app.state, "launch_command") and app.state.launch_command:
|
|
464
519
|
_launch_cmd = app.state.launch_command
|
|
465
520
|
# 调试输出
|
|
466
|
-
if _os.environ.get("
|
|
467
|
-
|
|
521
|
+
if _os.environ.get("debug_web_launch_cmd") == "1":
|
|
522
|
+
PrettyOutput.auto_print(
|
|
523
|
+
f"🔍 Web服务器: 使用传入的启动命令: {_launch_cmd}"
|
|
524
|
+
)
|
|
468
525
|
else:
|
|
469
526
|
# 回退到环境变量
|
|
470
527
|
import json as _json
|
|
471
|
-
|
|
528
|
+
|
|
529
|
+
_cmd_json = _os.environ.get("web_launch_json", "")
|
|
472
530
|
if _cmd_json:
|
|
473
531
|
try:
|
|
474
532
|
_launch_cmd = _json.loads(_cmd_json)
|
|
475
|
-
if _os.environ.get("
|
|
476
|
-
|
|
533
|
+
if _os.environ.get("debug_web_launch_cmd") == "1":
|
|
534
|
+
PrettyOutput.auto_print(
|
|
535
|
+
f"🔍 Web服务器: 从环境变量读取启动命令: {_launch_cmd}"
|
|
536
|
+
)
|
|
477
537
|
except Exception:
|
|
478
538
|
_launch_cmd = None
|
|
479
539
|
except Exception:
|
|
@@ -487,16 +547,21 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
487
547
|
# 子进程:执行启动命令,失败时回退到系统 shell
|
|
488
548
|
# 使用在 fork 前获取的命令
|
|
489
549
|
_argv = _launch_cmd
|
|
490
|
-
|
|
550
|
+
|
|
491
551
|
# 如果获取到有效命令,执行它
|
|
492
|
-
if
|
|
552
|
+
if (
|
|
553
|
+
_argv
|
|
554
|
+
and isinstance(_argv, list)
|
|
555
|
+
and len(_argv) > 0
|
|
556
|
+
and isinstance(_argv[0], str)
|
|
557
|
+
):
|
|
493
558
|
try:
|
|
494
|
-
if _os.environ.get("
|
|
495
|
-
|
|
559
|
+
if _os.environ.get("debug_web_launch_cmd") == "1":
|
|
560
|
+
PrettyOutput.auto_print(f"🔍 子进程: 执行命令: {_argv}")
|
|
496
561
|
_os.execvp(_argv[0], _argv)
|
|
497
562
|
except Exception as e:
|
|
498
|
-
if _os.environ.get("
|
|
499
|
-
|
|
563
|
+
if _os.environ.get("debug_web_launch_cmd") == "1":
|
|
564
|
+
PrettyOutput.auto_print(f"⚠️ 子进程: 执行命令失败: {e}")
|
|
500
565
|
pass
|
|
501
566
|
# 若未配置或执行失败,回退到 /bin/bash 或 /bin/sh
|
|
502
567
|
try:
|
|
@@ -530,7 +595,17 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
530
595
|
ok = _spawn_jvs_session()
|
|
531
596
|
if not ok:
|
|
532
597
|
try:
|
|
533
|
-
await ws.send_text(
|
|
598
|
+
await ws.send_text(
|
|
599
|
+
json.dumps(
|
|
600
|
+
{
|
|
601
|
+
"type": "output",
|
|
602
|
+
"payload": {
|
|
603
|
+
"text": "启动交互式终端失败",
|
|
604
|
+
"output_type": "ERROR",
|
|
605
|
+
},
|
|
606
|
+
}
|
|
607
|
+
)
|
|
608
|
+
)
|
|
534
609
|
except Exception:
|
|
535
610
|
pass
|
|
536
611
|
try:
|
|
@@ -555,7 +630,14 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
555
630
|
waiting_for_ack = False
|
|
556
631
|
if _spawn_jvs_session():
|
|
557
632
|
try:
|
|
558
|
-
await ws.send_text(
|
|
633
|
+
await ws.send_text(
|
|
634
|
+
json.dumps(
|
|
635
|
+
{
|
|
636
|
+
"type": "stdio",
|
|
637
|
+
"text": "\r\njvs 会话已重启\r\n",
|
|
638
|
+
}
|
|
639
|
+
)
|
|
640
|
+
)
|
|
559
641
|
except Exception:
|
|
560
642
|
pass
|
|
561
643
|
fd = session.get("master_fd")
|
|
@@ -568,7 +650,14 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
568
650
|
# 非确认流程:自动重启
|
|
569
651
|
if _spawn_jvs_session():
|
|
570
652
|
try:
|
|
571
|
-
await ws.send_text(
|
|
653
|
+
await ws.send_text(
|
|
654
|
+
json.dumps(
|
|
655
|
+
{
|
|
656
|
+
"type": "stdio",
|
|
657
|
+
"text": "\r\njvs 会话已重启\r\n",
|
|
658
|
+
}
|
|
659
|
+
)
|
|
660
|
+
)
|
|
572
661
|
except Exception:
|
|
573
662
|
pass
|
|
574
663
|
fd = session.get("master_fd")
|
|
@@ -591,7 +680,14 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
591
680
|
data = b""
|
|
592
681
|
if data:
|
|
593
682
|
try:
|
|
594
|
-
await ws.send_text(
|
|
683
|
+
await ws.send_text(
|
|
684
|
+
json.dumps(
|
|
685
|
+
{
|
|
686
|
+
"type": "stdio",
|
|
687
|
+
"text": data.decode(errors="ignore"),
|
|
688
|
+
}
|
|
689
|
+
)
|
|
690
|
+
)
|
|
595
691
|
except Exception:
|
|
596
692
|
break
|
|
597
693
|
else:
|
|
@@ -609,7 +705,14 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
609
705
|
# 标记等待用户回车,并提示
|
|
610
706
|
waiting_for_ack = True
|
|
611
707
|
try:
|
|
612
|
-
await ws.send_text(
|
|
708
|
+
await ws.send_text(
|
|
709
|
+
json.dumps(
|
|
710
|
+
{
|
|
711
|
+
"type": "stdio",
|
|
712
|
+
"text": "\r\nAgent 已结束。按回车继续,系统将重启新的 Agent。\r\n> ",
|
|
713
|
+
}
|
|
714
|
+
)
|
|
715
|
+
)
|
|
613
716
|
except Exception:
|
|
614
717
|
pass
|
|
615
718
|
# 不立即重启,等待顶部 fd None 分支在收到回车后处理
|
|
@@ -645,7 +748,17 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
645
748
|
pass
|
|
646
749
|
# 发送就绪提示
|
|
647
750
|
try:
|
|
648
|
-
await ws.send_text(
|
|
751
|
+
await ws.send_text(
|
|
752
|
+
json.dumps(
|
|
753
|
+
{
|
|
754
|
+
"type": "output",
|
|
755
|
+
"payload": {
|
|
756
|
+
"text": "交互式终端已就绪(PTY)",
|
|
757
|
+
"output_type": "INFO",
|
|
758
|
+
},
|
|
759
|
+
}
|
|
760
|
+
)
|
|
761
|
+
)
|
|
649
762
|
except Exception:
|
|
650
763
|
pass
|
|
651
764
|
|
|
@@ -672,12 +785,22 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
672
785
|
else:
|
|
673
786
|
# 非回车输入时轻提示
|
|
674
787
|
try:
|
|
675
|
-
await ws.send_text(
|
|
788
|
+
await ws.send_text(
|
|
789
|
+
json.dumps(
|
|
790
|
+
{
|
|
791
|
+
"type": "stdio",
|
|
792
|
+
"text": "\r\n按回车继续。\r\n> ",
|
|
793
|
+
}
|
|
794
|
+
)
|
|
795
|
+
)
|
|
676
796
|
except Exception:
|
|
677
797
|
pass
|
|
678
798
|
else:
|
|
679
799
|
# 原样写入(保留控制字符);前端可按需发送回车
|
|
680
|
-
_os.write(
|
|
800
|
+
_os.write(
|
|
801
|
+
session.get("master_fd") or -1,
|
|
802
|
+
text.encode(errors="ignore"),
|
|
803
|
+
)
|
|
681
804
|
except Exception:
|
|
682
805
|
pass
|
|
683
806
|
elif mtype == "resize":
|
|
@@ -723,6 +846,7 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
723
846
|
pid_val = session.get("pid")
|
|
724
847
|
if isinstance(pid_val, int):
|
|
725
848
|
import signal as _signal
|
|
849
|
+
|
|
726
850
|
try:
|
|
727
851
|
_os.kill(pid_val, _signal.SIGTERM)
|
|
728
852
|
except Exception:
|
|
@@ -734,7 +858,7 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
734
858
|
except Exception:
|
|
735
859
|
pass
|
|
736
860
|
|
|
737
|
-
|
|
861
|
+
PrettyOutput.auto_print(f"✅ 启动 Jarvis Web 服务: http://{host}:{port}")
|
|
738
862
|
# 在服务端进程内也写入并维护 PID 文件,增强可检测性与可清理性
|
|
739
863
|
try:
|
|
740
864
|
pidfile = Path(os.path.expanduser("~/.jarvis")) / f"jarvis_web_{port}.pid"
|
|
@@ -746,16 +870,19 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
746
870
|
pidfile.write_text(str(os.getpid()), encoding="utf-8")
|
|
747
871
|
except Exception:
|
|
748
872
|
pass
|
|
873
|
+
|
|
749
874
|
# 退出时清理 PID 文件
|
|
750
875
|
def _cleanup_pidfile() -> None:
|
|
751
876
|
try:
|
|
752
877
|
pidfile.unlink(missing_ok=True)
|
|
753
878
|
except Exception:
|
|
754
879
|
pass
|
|
880
|
+
|
|
755
881
|
try:
|
|
756
882
|
atexit.register(_cleanup_pidfile)
|
|
757
883
|
except Exception:
|
|
758
884
|
pass
|
|
885
|
+
|
|
759
886
|
# 处理 SIGTERM/SIGINT,清理后退出
|
|
760
887
|
def _signal_handler(signum: int, frame: Any) -> None:
|
|
761
888
|
try:
|
|
@@ -765,6 +892,7 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
765
892
|
os._exit(0)
|
|
766
893
|
except Exception:
|
|
767
894
|
pass
|
|
895
|
+
|
|
768
896
|
try:
|
|
769
897
|
signal.signal(signal.SIGTERM, _signal_handler)
|
|
770
898
|
except Exception:
|
|
@@ -777,6 +905,7 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, laun
|
|
|
777
905
|
pass
|
|
778
906
|
# 配置 uvicorn 日志级别,隐藏连接信息和访问日志
|
|
779
907
|
import logging
|
|
908
|
+
|
|
780
909
|
# 禁用 uvicorn 的访问日志
|
|
781
910
|
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
|
|
782
911
|
# 禁用 uvicorn 的常规日志(连接信息等)
|
jarvis/jarvis_c2rust/__init__.py
CHANGED