myagent-ai 1.15.34 → 1.15.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/agents/main_agent.py +39 -0
- package/core/deps_checker.py +3 -1
- package/core/output_parser.py +63 -25
- package/package.json +1 -1
- package/requirements.txt +2 -6
- package/setup.py +7 -8
- package/start.js +17 -7
- package/start.sh +2 -2
- package/agents/__pycache__/main_agent.cpython-312.pyc +0 -0
- package/agents/__pycache__/memory_agent.cpython-312.pyc +0 -0
- package/core/__pycache__/context_builder.cpython-312.pyc +0 -0
- package/core/__pycache__/output_parser.cpython-312.pyc +0 -0
- package/memory/__pycache__/manager.cpython-312.pyc +0 -0
- package/skills/__pycache__/browser_skill.cpython-312.pyc +0 -0
- package/skills/__pycache__/file_skill.cpython-312.pyc +0 -0
- package/skills/__pycache__/registry.cpython-312.pyc +0 -0
- package/web/__pycache__/api_server.cpython-312.pyc +0 -0
package/README.md
CHANGED
|
@@ -123,6 +123,20 @@ powershell -c "irm https://raw.githubusercontent.com/ctz168/myagent/main/install
|
|
|
123
123
|
curl -fsSL https://raw.githubusercontent.com/ctz168/myagent/main/install/install.sh | bash
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
+
### 一键重装(跳过依赖检查)
|
|
127
|
+
|
|
128
|
+
> 已安装过 MyAgent 的环境下,快速升级/重装,不检查 Python/Node.js 和 pip 依赖。
|
|
129
|
+
|
|
130
|
+
**Windows(PowerShell):**
|
|
131
|
+
```powershell
|
|
132
|
+
powershell -c "& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ctz168/myagent/main/install/install.ps1))) -NoDeps"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**macOS / Linux:**
|
|
136
|
+
```bash
|
|
137
|
+
curl -fsSL https://raw.githubusercontent.com/ctz168/myagent/main/install/install.sh | bash -s -- --no-deps
|
|
138
|
+
```
|
|
139
|
+
|
|
126
140
|
---
|
|
127
141
|
|
|
128
142
|
## 📋 系统要求
|
package/agents/main_agent.py
CHANGED
|
@@ -637,10 +637,49 @@ class MainAgent(BaseAgent):
|
|
|
637
637
|
"response": truncate_str(parsed.response, 500),
|
|
638
638
|
"parse_success": parsed.parse_success,
|
|
639
639
|
"needs_correction": parsed.needs_correction,
|
|
640
|
+
"output_block_complete": parsed.output_block_complete,
|
|
640
641
|
}},
|
|
641
642
|
stream_callback,
|
|
642
643
|
)
|
|
643
644
|
|
|
645
|
+
# Step 4.2: <output> 块完整性检查 — 不完整的块不输出,触发修正
|
|
646
|
+
if not parsed.output_block_complete:
|
|
647
|
+
logger.warning(
|
|
648
|
+
f"[{task_id}] <output> 块不完整(缺少 </output> 闭合标签),"
|
|
649
|
+
f"跳过本轮输出和工具执行"
|
|
650
|
+
)
|
|
651
|
+
if _xml_correction_retries < 1:
|
|
652
|
+
_xml_correction_retries += 1
|
|
653
|
+
correction_prompt = (
|
|
654
|
+
"你的输出缺少 </output> 闭合标签,XML块不完整,"
|
|
655
|
+
"解析器不会处理不完整的块。\n"
|
|
656
|
+
"请严格按照 <output>...</output> 格式重新输出,"
|
|
657
|
+
"确保所有标签正确闭合。\n\n"
|
|
658
|
+
f"你上一次的原始输出如下:\n{llm_raw}"
|
|
659
|
+
)
|
|
660
|
+
conversation_history.append(
|
|
661
|
+
Message(role="assistant", content=llm_raw)
|
|
662
|
+
)
|
|
663
|
+
conversation_history.append(
|
|
664
|
+
Message(role="user", content=correction_prompt)
|
|
665
|
+
)
|
|
666
|
+
await self._emit_v2_event(
|
|
667
|
+
"v2_reasoning",
|
|
668
|
+
{"content": "⚠️ 模型输出XML块不完整,正在自动修正..."},
|
|
669
|
+
stream_callback,
|
|
670
|
+
)
|
|
671
|
+
continue # 重新进入循环,让 LLM 重新生成
|
|
672
|
+
else:
|
|
673
|
+
# 已重试过,强制终止并提示用户
|
|
674
|
+
logger.warning(f"[{task_id}] XML块仍不完整且已重试,终止循环")
|
|
675
|
+
context.working_memory["final_response"] = "模型输出格式异常,请重新尝试。"
|
|
676
|
+
await self._emit_v2_event(
|
|
677
|
+
"v2_reasoning",
|
|
678
|
+
{"content": "模型输出格式异常,已自动终止。"},
|
|
679
|
+
stream_callback,
|
|
680
|
+
)
|
|
681
|
+
break
|
|
682
|
+
|
|
644
683
|
# Step 4.5: 解析失败处理 — 回退给 LLM 修正或提取周边文本
|
|
645
684
|
if not parsed.parse_success:
|
|
646
685
|
# 即使解析失败,如果 regex fallback 提取到了工具调用,仍然继续执行
|
package/core/deps_checker.py
CHANGED
|
@@ -12,7 +12,7 @@ core/deps_checker.py - 自动依赖检测与安装
|
|
|
12
12
|
|
|
13
13
|
依赖映射:
|
|
14
14
|
核心功能: openai, aiohttp, requests
|
|
15
|
-
搜索技能: bs4
|
|
15
|
+
搜索技能: duckduckgo_search, bs4, lxml
|
|
16
16
|
系统技能: psutil
|
|
17
17
|
托盘功能: pystray, PIL
|
|
18
18
|
语音合成: edge_tts
|
|
@@ -62,7 +62,9 @@ DEPENDENCIES: List[DepInfo] = [
|
|
|
62
62
|
DepInfo("requests", "requests", "2.31.0", "core", "all"),
|
|
63
63
|
|
|
64
64
|
# ── 搜索技能 ──
|
|
65
|
+
DepInfo("duckduckgo_search", "duckduckgo-search", "6.0.0", "search", "all"),
|
|
65
66
|
DepInfo("bs4", "beautifulsoup4", "4.12.0", "search", "all"),
|
|
67
|
+
DepInfo("lxml", "lxml", "5.0.0", "search", "all"),
|
|
66
68
|
|
|
67
69
|
# ── 系统技能 ──
|
|
68
70
|
DepInfo("psutil", "psutil", "5.9.0", "system", "all"),
|
package/core/output_parser.py
CHANGED
|
@@ -152,6 +152,7 @@ class ParsedOutput:
|
|
|
152
152
|
raw_text: str = ""
|
|
153
153
|
parse_success: bool = False
|
|
154
154
|
needs_correction: bool = False
|
|
155
|
+
output_block_complete: bool = False # </output> 闭合标签是否存在
|
|
155
156
|
|
|
156
157
|
|
|
157
158
|
# ---------------------------------------------------------------------------
|
|
@@ -191,7 +192,7 @@ def _canonical_tag(tag_name: str) -> str:
|
|
|
191
192
|
return _ALIAS_TO_CANONICAL.get(lower, lower)
|
|
192
193
|
|
|
193
194
|
|
|
194
|
-
def _extract_tag_content(text: str, tag_name: str, stop_tags: List[str] | None = None) -> str:
|
|
195
|
+
def _extract_tag_content(text: str, tag_name: str, stop_tags: List[str] | None = None, *, conservative: bool = False) -> str:
|
|
195
196
|
"""Extract the text content of ``<tag_name>…</tag_name>`` from *text*.
|
|
196
197
|
|
|
197
198
|
Fault-tolerant strategies tried in order:
|
|
@@ -226,6 +227,10 @@ def _extract_tag_content(text: str, tag_name: str, stop_tags: List[str] | None =
|
|
|
226
227
|
if m:
|
|
227
228
|
return m.group(1)
|
|
228
229
|
|
|
230
|
+
# Conservative mode: only extract properly closed tags, skip all fallbacks
|
|
231
|
+
if conservative:
|
|
232
|
+
return ""
|
|
233
|
+
|
|
229
234
|
# Strategy 2: Unclosed — content runs until the next opening/closing
|
|
230
235
|
# sibling tag or </output>.
|
|
231
236
|
sibling_names = [t for t in stop_tags if t.lower() != tag_name.lower()]
|
|
@@ -270,6 +275,8 @@ def _extract_all_tag_blocks(
|
|
|
270
275
|
text: str,
|
|
271
276
|
tag_name: str,
|
|
272
277
|
parent_close_tag: str | None = None,
|
|
278
|
+
*,
|
|
279
|
+
conservative: bool = False,
|
|
273
280
|
) -> List[str]:
|
|
274
281
|
"""Extract all ``<tag_name>…`` blocks from *text*.
|
|
275
282
|
|
|
@@ -293,6 +300,10 @@ def _extract_all_tag_blocks(
|
|
|
293
300
|
if properly_closed:
|
|
294
301
|
return properly_closed
|
|
295
302
|
|
|
303
|
+
# Conservative mode: only extract properly closed blocks
|
|
304
|
+
if conservative:
|
|
305
|
+
return []
|
|
306
|
+
|
|
296
307
|
# Strategy 2: Split by <tag> openings — each segment is a block
|
|
297
308
|
positions = [
|
|
298
309
|
m.end() for m in re.finditer(rf"<{tag_esc}[^>]*>", text, re.IGNORECASE)
|
|
@@ -377,6 +388,22 @@ def _strip_outer_noise(text: str) -> str:
|
|
|
377
388
|
return text
|
|
378
389
|
|
|
379
390
|
|
|
391
|
+
def is_output_block_complete(raw_text: str) -> bool:
|
|
392
|
+
"""Check if *raw_text* contains a properly closed ``<output>...</output>`` block.
|
|
393
|
+
|
|
394
|
+
Returns:
|
|
395
|
+
True if both ``<output>`` and ``</output>`` tags are present.
|
|
396
|
+
False if neither tag, or only the opening tag, is found.
|
|
397
|
+
"""
|
|
398
|
+
if not raw_text:
|
|
399
|
+
return False
|
|
400
|
+
open_m = re.search(r"<output[^>]*>", raw_text, re.IGNORECASE)
|
|
401
|
+
if open_m is None:
|
|
402
|
+
return False
|
|
403
|
+
close_m = re.search(r"</output\s*>", raw_text[open_m.end():], re.IGNORECASE)
|
|
404
|
+
return close_m is not None
|
|
405
|
+
|
|
406
|
+
|
|
380
407
|
# ---------------------------------------------------------------------------
|
|
381
408
|
# Core custom parser — NO xml.etree.ElementTree
|
|
382
409
|
# ---------------------------------------------------------------------------
|
|
@@ -399,63 +426,73 @@ def _custom_parse(raw_text: str) -> ParsedOutput:
|
|
|
399
426
|
parsed.needs_correction = True
|
|
400
427
|
return parsed
|
|
401
428
|
|
|
429
|
+
# ── Step 0: Check <output> block completeness ──
|
|
430
|
+
parsed.output_block_complete = is_output_block_complete(raw_text)
|
|
431
|
+
conservative = not parsed.output_block_complete
|
|
432
|
+
|
|
433
|
+
if conservative:
|
|
434
|
+
logger.info(
|
|
435
|
+
"XML <output> 块不完整(缺少 </output> 闭合标签),"
|
|
436
|
+
"启用保守解析模式(仅提取完整闭合的标签)"
|
|
437
|
+
)
|
|
438
|
+
|
|
402
439
|
# ── Step 1: Strip non-XML noise (text before/after <output>) ──
|
|
403
440
|
body = _strip_outer_noise(raw_text)
|
|
404
441
|
|
|
405
442
|
# ── Step 2: Extract each known top-level tag ──
|
|
406
443
|
|
|
407
444
|
# usersays_correct
|
|
408
|
-
raw_val = _extract_tag_content(body, "usersays_correct")
|
|
445
|
+
raw_val = _extract_tag_content(body, "usersays_correct", conservative=conservative)
|
|
409
446
|
parsed.usersays_correct = _safe_strip(raw_val)
|
|
410
447
|
|
|
411
448
|
# task_plan
|
|
412
|
-
raw_val = _extract_tag_content(body, "task_plan")
|
|
449
|
+
raw_val = _extract_tag_content(body, "task_plan", conservative=conservative)
|
|
413
450
|
parsed.task_plan = _safe_strip(raw_val)
|
|
414
451
|
|
|
415
452
|
# response
|
|
416
|
-
raw_val = _extract_tag_content(body, "response")
|
|
453
|
+
raw_val = _extract_tag_content(body, "response", conservative=conservative)
|
|
417
454
|
parsed.response = _safe_strip(raw_val)
|
|
418
455
|
|
|
419
456
|
# recall
|
|
420
|
-
raw_val = _extract_tag_content(body, "recall")
|
|
457
|
+
raw_val = _extract_tag_content(body, "recall", conservative=conservative)
|
|
421
458
|
parsed.recall = _safe_strip(raw_val)
|
|
422
459
|
|
|
423
460
|
# knowledge
|
|
424
|
-
raw_val = _extract_tag_content(body, "knowledge")
|
|
461
|
+
raw_val = _extract_tag_content(body, "knowledge", conservative=conservative)
|
|
425
462
|
parsed.knowledge = _safe_strip(raw_val)
|
|
426
463
|
|
|
427
464
|
# askuser (also try alias ask_user)
|
|
428
|
-
raw_val = _extract_tag_content(body, "askuser")
|
|
465
|
+
raw_val = _extract_tag_content(body, "askuser", conservative=conservative)
|
|
429
466
|
if not raw_val.strip():
|
|
430
|
-
raw_val = _extract_tag_content(body, "ask_user")
|
|
467
|
+
raw_val = _extract_tag_content(body, "ask_user", conservative=conservative)
|
|
431
468
|
parsed.ask_user = _safe_strip(raw_val)
|
|
432
469
|
|
|
433
470
|
# get_knowledge
|
|
434
|
-
raw_val = _extract_tag_content(body, "get_knowledge")
|
|
471
|
+
raw_val = _extract_tag_content(body, "get_knowledge", conservative=conservative)
|
|
435
472
|
parsed.get_knowledge = _safe_strip(raw_val)
|
|
436
473
|
|
|
437
474
|
# finish
|
|
438
|
-
raw_val = _extract_tag_content(body, "finish")
|
|
475
|
+
raw_val = _extract_tag_content(body, "finish", conservative=conservative)
|
|
439
476
|
parsed.finish = _parse_bool(raw_val, False)
|
|
440
477
|
|
|
441
478
|
# finish_reason
|
|
442
|
-
raw_val = _extract_tag_content(body, "finish_reason")
|
|
479
|
+
raw_val = _extract_tag_content(body, "finish_reason", conservative=conservative)
|
|
443
480
|
parsed.finish_reason = _safe_strip(raw_val)
|
|
444
481
|
|
|
445
482
|
# next_step
|
|
446
|
-
raw_val = _extract_tag_content(body, "next_step")
|
|
483
|
+
raw_val = _extract_tag_content(body, "next_step", conservative=conservative)
|
|
447
484
|
parsed.next_step = _safe_strip(raw_val)
|
|
448
485
|
|
|
449
486
|
# mainsubject [v1.15.8] 会话标题自动命名
|
|
450
|
-
raw_val = _extract_tag_content(body, "mainsubject")
|
|
487
|
+
raw_val = _extract_tag_content(body, "mainsubject", conservative=conservative)
|
|
451
488
|
parsed.mainsubject = _safe_strip(raw_val)
|
|
452
489
|
|
|
453
490
|
# ── Step 3: Parse <remember> (may contain <type> and <content>) ──
|
|
454
|
-
remember_raw = _extract_tag_content(body, "remember")
|
|
491
|
+
remember_raw = _extract_tag_content(body, "remember", conservative=conservative)
|
|
455
492
|
if remember_raw.strip():
|
|
456
493
|
# Try structured format: <type>global</type><content>...</content>
|
|
457
|
-
type_val = _extract_tag_content(remember_raw, "type", REMEMBER_INNER_TAGS)
|
|
458
|
-
content_val = _extract_tag_content(remember_raw, "content", REMEMBER_INNER_TAGS)
|
|
494
|
+
type_val = _extract_tag_content(remember_raw, "type", REMEMBER_INNER_TAGS, conservative=conservative)
|
|
495
|
+
content_val = _extract_tag_content(remember_raw, "content", REMEMBER_INNER_TAGS, conservative=conservative)
|
|
459
496
|
|
|
460
497
|
if content_val.strip():
|
|
461
498
|
mem_type = _safe_strip(type_val) or "session"
|
|
@@ -469,9 +506,9 @@ def _custom_parse(raw_text: str) -> ParsedOutput:
|
|
|
469
506
|
parsed.remember_type = "session"
|
|
470
507
|
|
|
471
508
|
# ── Step 4: Parse <toolstocal> → list of tool dicts ──
|
|
472
|
-
toolstocal_raw = _extract_tag_content(body, "toolstocal")
|
|
509
|
+
toolstocal_raw = _extract_tag_content(body, "toolstocal", conservative=conservative)
|
|
473
510
|
if toolstocal_raw.strip():
|
|
474
|
-
parsed.tools_to_call = _parse_toolstocal(toolstocal_raw)
|
|
511
|
+
parsed.tools_to_call = _parse_toolstocal(toolstocal_raw, conservative=conservative)
|
|
475
512
|
|
|
476
513
|
# ── Step 5: Determine parse success ──
|
|
477
514
|
has_content = bool(
|
|
@@ -516,31 +553,32 @@ def _custom_parse(raw_text: str) -> ParsedOutput:
|
|
|
516
553
|
return parsed
|
|
517
554
|
|
|
518
555
|
|
|
519
|
-
def _parse_toolstocal(toolstocal_content: str) -> List[Dict[str, Any]]:
|
|
556
|
+
def _parse_toolstocal(toolstocal_content: str, *, conservative: bool = False) -> List[Dict[str, Any]]:
|
|
520
557
|
"""Parse ``<toolstocal>`` body into a list of tool descriptors."""
|
|
521
558
|
tools: List[Dict[str, Any]] = []
|
|
522
559
|
|
|
523
560
|
tool_blocks = _extract_all_tag_blocks(
|
|
524
|
-
toolstocal_content, "tool", parent_close_tag="</toolstocal>"
|
|
561
|
+
toolstocal_content, "tool", parent_close_tag="</toolstocal>",
|
|
562
|
+
conservative=conservative,
|
|
525
563
|
)
|
|
526
564
|
|
|
527
565
|
for block in tool_blocks:
|
|
528
566
|
tool: Dict[str, Any] = {
|
|
529
567
|
"beforecalltext": _safe_strip(
|
|
530
|
-
_extract_tag_content(block, "beforecalltext", TOOL_INNER_TAGS)
|
|
568
|
+
_extract_tag_content(block, "beforecalltext", TOOL_INNER_TAGS, conservative=conservative)
|
|
531
569
|
),
|
|
532
570
|
"toolname": _safe_strip(
|
|
533
|
-
_extract_tag_content(block, "toolname", TOOL_INNER_TAGS)
|
|
571
|
+
_extract_tag_content(block, "toolname", TOOL_INNER_TAGS, conservative=conservative)
|
|
534
572
|
),
|
|
535
573
|
"parms": _safe_strip(
|
|
536
|
-
_extract_tag_content(block, "parms", TOOL_INNER_TAGS)
|
|
574
|
+
_extract_tag_content(block, "parms", TOOL_INNER_TAGS, conservative=conservative)
|
|
537
575
|
),
|
|
538
576
|
"timeout": _parse_int(
|
|
539
|
-
_extract_tag_content(block, "timeout", TOOL_INNER_TAGS),
|
|
577
|
+
_extract_tag_content(block, "timeout", TOOL_INNER_TAGS, conservative=conservative),
|
|
540
578
|
_DEFAULT_TIMEOUT,
|
|
541
579
|
),
|
|
542
580
|
"callback": _parse_bool(
|
|
543
|
-
_extract_tag_content(block, "callback", TOOL_INNER_TAGS),
|
|
581
|
+
_extract_tag_content(block, "callback", TOOL_INNER_TAGS, conservative=conservative),
|
|
544
582
|
_DEFAULT_CALLBACK,
|
|
545
583
|
),
|
|
546
584
|
}
|
package/package.json
CHANGED
package/requirements.txt
CHANGED
|
@@ -11,8 +11,9 @@ requests>=2.31.0
|
|
|
11
11
|
# ============================================================
|
|
12
12
|
# 技能系统 - 搜索
|
|
13
13
|
# ============================================================
|
|
14
|
-
|
|
14
|
+
duckduckgo-search>=6.0.0
|
|
15
15
|
beautifulsoup4>=4.12.0
|
|
16
|
+
lxml>=5.0.0
|
|
16
17
|
psutil>=5.9.0
|
|
17
18
|
|
|
18
19
|
# ============================================================
|
|
@@ -54,11 +55,6 @@ edge-tts>=6.1.0
|
|
|
54
55
|
# ============================================================
|
|
55
56
|
faster-whisper>=1.0.0
|
|
56
57
|
|
|
57
|
-
# ============================================================
|
|
58
|
-
# 音频处理 (TTS 服务端处理)
|
|
59
|
-
# ============================================================
|
|
60
|
-
pydub>=0.25.1
|
|
61
|
-
|
|
62
58
|
# ============================================================
|
|
63
59
|
# Anthropic Claude (可选)
|
|
64
60
|
# ============================================================
|
package/setup.py
CHANGED
|
@@ -27,19 +27,22 @@ setup(
|
|
|
27
27
|
"openai>=1.12.0",
|
|
28
28
|
"aiohttp>=3.9.0",
|
|
29
29
|
"requests>=2.31.0",
|
|
30
|
-
# 搜索
|
|
30
|
+
# 搜索
|
|
31
|
+
"duckduckgo-search>=6.0.0",
|
|
31
32
|
"beautifulsoup4>=4.12.0",
|
|
33
|
+
"lxml>=5.0.0",
|
|
32
34
|
"psutil>=5.9.0",
|
|
33
|
-
#
|
|
35
|
+
# 系统托盘
|
|
36
|
+
"pystray>=0.19.5",
|
|
34
37
|
"Pillow>=10.0.0",
|
|
35
38
|
# 语音合成
|
|
36
39
|
"edge-tts>=6.1.0",
|
|
37
40
|
# 语音识别 (本地 STT)
|
|
38
41
|
"faster-whisper>=1.0.0",
|
|
39
|
-
#
|
|
40
|
-
"pydub>=0.25.1",
|
|
42
|
+
# 浏览器自动化 (ChromeDev MCP, 无需 Playwright)
|
|
41
43
|
# 桌面 GUI 自动化 (内置技能)
|
|
42
44
|
"pynput>=1.7.6",
|
|
45
|
+
"pygetwindow>=0.0.9",
|
|
43
46
|
"mss>=9.0.0",
|
|
44
47
|
],
|
|
45
48
|
extras_require={
|
|
@@ -47,8 +50,6 @@ setup(
|
|
|
47
50
|
"discord": ["discord.py>=2.3.0"],
|
|
48
51
|
"anthropic": ["anthropic>=0.18.0"],
|
|
49
52
|
"communication": ["cryptography>=41.0.0", "websockets>=12.0"],
|
|
50
|
-
"tray": ["pystray>=0.19.5"],
|
|
51
|
-
"gui": ["pygetwindow>=0.0.9"],
|
|
52
53
|
"voice": ["faster-whisper>=1.0.0"],
|
|
53
54
|
"all": [
|
|
54
55
|
"python-telegram-bot>=21.0",
|
|
@@ -56,8 +57,6 @@ setup(
|
|
|
56
57
|
"anthropic>=0.18.0",
|
|
57
58
|
"cryptography>=41.0.0",
|
|
58
59
|
"websockets>=12.0",
|
|
59
|
-
"pystray>=0.19.5",
|
|
60
|
-
"pygetwindow>=0.0.9",
|
|
61
60
|
"faster-whisper>=1.0.0",
|
|
62
61
|
],
|
|
63
62
|
},
|
package/start.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* myagent-ai setup # 配置向导
|
|
18
18
|
* myagent-ai reinstall # 重新安装依赖到 venv
|
|
19
19
|
* myagent-ai uninstall # 卸载 MyAgent(删除npm包+数据)
|
|
20
|
+
* myagent-ai --skip-deps # 跳过依赖检查,直接启动
|
|
20
21
|
*/
|
|
21
22
|
"use strict";
|
|
22
23
|
|
|
@@ -264,11 +265,11 @@ function parseRequirements(reqFile) {
|
|
|
264
265
|
// 特殊映射: pip 包名和 import 名不一致的
|
|
265
266
|
const importMap = {
|
|
266
267
|
"beautifulsoup4": "bs4",
|
|
268
|
+
"py_getwindow": "pygetwindow",
|
|
267
269
|
"python_telegram_bot": "telegram",
|
|
268
270
|
"pillow": "PIL",
|
|
269
271
|
"psutil": "psutil",
|
|
270
272
|
"edge_tts": "edge_tts",
|
|
271
|
-
"pydub": "pydub",
|
|
272
273
|
};
|
|
273
274
|
modules.push(importMap[pkg] || pkg);
|
|
274
275
|
}
|
|
@@ -286,12 +287,14 @@ const CORE_PACKAGES = [
|
|
|
286
287
|
"openai>=1.12.0",
|
|
287
288
|
"aiohttp>=3.9.0",
|
|
288
289
|
"requests>=2.31.0",
|
|
290
|
+
"duckduckgo-search>=6.0.0",
|
|
289
291
|
"beautifulsoup4>=4.12.0",
|
|
292
|
+
"lxml>=5.0.0",
|
|
290
293
|
"psutil>=5.9.0",
|
|
294
|
+
"pystray>=0.19.5",
|
|
291
295
|
"Pillow>=10.0.0",
|
|
292
296
|
"edge-tts>=6.1.0",
|
|
293
297
|
"faster-whisper>=1.0.0",
|
|
294
|
-
"pydub>=0.25.1",
|
|
295
298
|
"anthropic>=0.18.0",
|
|
296
299
|
];
|
|
297
300
|
|
|
@@ -522,11 +525,18 @@ function main() {
|
|
|
522
525
|
console.log(" \x1b[1m\x1b[36mMyAgent\x1b[0m - 本地桌面端执行型 AI 助手");
|
|
523
526
|
console.log("");
|
|
524
527
|
|
|
528
|
+
// 是否跳过依赖检查
|
|
529
|
+
const skipDeps = userArgs.includes("--skip-deps") || userArgs.includes("--no-deps");
|
|
530
|
+
// 从参数中移除 --skip-deps/--no-deps,避免传入 main.py
|
|
531
|
+
const filteredArgs = userArgs.filter(a => a !== "--skip-deps" && a !== "--no-deps");
|
|
532
|
+
|
|
525
533
|
// 确保 venv 存在
|
|
526
534
|
const { venvDir, venvPython, isNew } = ensureVenv();
|
|
527
535
|
|
|
528
|
-
//
|
|
529
|
-
if (
|
|
536
|
+
// 检查并安装依赖(--skip-deps 时跳过)
|
|
537
|
+
if (skipDeps) {
|
|
538
|
+
console.log(" \x1b[90m[i]\x1b[0m 跳过依赖检查(--skip-deps)");
|
|
539
|
+
} else if (isNew) {
|
|
530
540
|
installDeps(venvPython, getVenvPip(venvDir), pkgDir);
|
|
531
541
|
} else {
|
|
532
542
|
// 即使 venv 已存在,也快速检查核心依赖
|
|
@@ -548,9 +558,9 @@ function main() {
|
|
|
548
558
|
console.log(` \x1b[90m[i]\x1b[0m Python: ${venvPython}`);
|
|
549
559
|
console.log("");
|
|
550
560
|
|
|
551
|
-
// 构建 Python
|
|
552
|
-
let mode =
|
|
553
|
-
let pyArgs = buildArgs(
|
|
561
|
+
// 构建 Python 参数(使用过滤后的参数)
|
|
562
|
+
let mode = filteredArgs[0] || "";
|
|
563
|
+
let pyArgs = buildArgs(filteredArgs);
|
|
554
564
|
|
|
555
565
|
// 首次运行且未指定模式 → 自动选择 web 模式
|
|
556
566
|
if (isFirstRun && !mode) {
|
package/start.sh
CHANGED
|
@@ -137,8 +137,8 @@ install_deps() {
|
|
|
137
137
|
# fallback: 直接安装核心包
|
|
138
138
|
"$VENV_PY" -m pip install --quiet \
|
|
139
139
|
"openai>=1.12.0" "aiohttp>=3.9.0" "requests>=2.31.0" \
|
|
140
|
-
"beautifulsoup4>=4.12.0" \
|
|
141
|
-
"psutil>=5.9.0" --disable-pip-version-check 2>/dev/null || true
|
|
140
|
+
"duckduckgo-search>=6.0.0" "beautifulsoup4>=4.12.0" \
|
|
141
|
+
"lxml>=5.0.0" "psutil>=5.9.0" --disable-pip-version-check 2>/dev/null || true
|
|
142
142
|
success "核心依赖安装完成"
|
|
143
143
|
fi
|
|
144
144
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|