mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-01 01:10:21 +08:00
* feat: filesystem grep, read, edit file * feat: add file write tool and enhance file read functionality * feat: enhance tool prompt formatting and add escaped text decoding for file editing * feat: remove redundant safe path tests from security restrictions * feat: implement file read tool with support for text and image files, including validation for large files * feat: add file read utilities and integrate with filesystem tools * refactor: move computer tools to builtin tools registry * refactor: remove unused plugin_context parameter from _apply_sandbox_tools * feat: supports to display enabled builtin tools in configs * feat: add tooltip for disabled builtin tools and update localization strings * feat: add workspace extra prompt handling in message processing * feat: add ripgrep installation to Dockerfile * perf: shell executed in workspace dir in local env * feat: enhance file reading capabilities to support PDF and DOCX parsing, including workspace storage for long documents * feat: update converted text notice to suggest using grep for large files * feat: implement handling for large tool results with overflow file writing and read tool integration * fix: test * feat: enhance onboarding steps to include computer access configuration and related help information * feat: add support for additional temporary path in restricted environment checks * feat: update computer access hints and add detailed configuration instructions
89 lines
2.3 KiB
Python
89 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from types import SimpleNamespace
|
|
|
|
from astrbot.core.agent.run_context import ContextWrapper
|
|
from astrbot.core.tools.computer_tools.shipyard_neo.neo_skills import (
|
|
PromoteSkillCandidateTool,
|
|
)
|
|
|
|
|
|
class _FakeSkills:
|
|
def __init__(self):
|
|
self.rollback_called_with = None
|
|
|
|
async def promote_candidate(self, candidate_id: str, stage: str = "canary"):
|
|
assert candidate_id == "cand-1"
|
|
assert stage == "stable"
|
|
return {
|
|
"id": "sr-1",
|
|
"skill_key": "k1",
|
|
"candidate_id": candidate_id,
|
|
"stage": stage,
|
|
}
|
|
|
|
async def rollback_release(self, release_id: str):
|
|
self.rollback_called_with = release_id
|
|
return {"id": "rb-1", "rollback_of": release_id}
|
|
|
|
|
|
class _FakeClient:
|
|
def __init__(self):
|
|
self.skills = _FakeSkills()
|
|
|
|
|
|
class _FakeBooter:
|
|
def __init__(self):
|
|
self.bay_client = _FakeClient()
|
|
self.sandbox = object()
|
|
|
|
|
|
def test_promote_stable_sync_failure_auto_rolls_back(monkeypatch):
|
|
async def _fake_get_booter(_ctx, _session_id):
|
|
return _FakeBooter()
|
|
|
|
async def _fake_sync_release(self, client, **kwargs):
|
|
_ = self, client, kwargs
|
|
raise ValueError("sync failed")
|
|
|
|
monkeypatch.setattr(
|
|
"astrbot.core.tools.computer_tools.shipyard_neo.neo_skills.get_booter",
|
|
_fake_get_booter,
|
|
)
|
|
monkeypatch.setattr(
|
|
"astrbot.core.tools.computer_tools.shipyard_neo.neo_skills.NeoSkillSyncManager.sync_release",
|
|
_fake_sync_release,
|
|
)
|
|
|
|
event = SimpleNamespace(
|
|
role="admin",
|
|
unified_msg_origin="session-1",
|
|
get_sender_id=lambda: "admin-user",
|
|
)
|
|
astr_ctx = SimpleNamespace(
|
|
context=SimpleNamespace(
|
|
get_config=lambda umo: { # noqa: ARG005
|
|
"provider_settings": {
|
|
"computer_use_require_admin": True,
|
|
}
|
|
}
|
|
),
|
|
event=event,
|
|
)
|
|
run_ctx = ContextWrapper(context=astr_ctx)
|
|
|
|
tool = PromoteSkillCandidateTool()
|
|
result = asyncio.run(
|
|
tool.call(
|
|
run_ctx,
|
|
candidate_id="cand-1",
|
|
stage="stable",
|
|
sync_to_local=True,
|
|
)
|
|
)
|
|
|
|
assert isinstance(result, str)
|
|
assert "auto rollback succeeded" in result
|
|
assert "sync failed" in result
|