[project] name = "pineagents" dynamic = ["version"] description = "QwenPaw is a **personal assistant** that runs in your own environment. It talks to you over multiple channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.) and runs scheduled tasks according to your configuration. **What it can do is driven by Skills — the possibilities are open-ended.** Built-in skills include cron, PDF/Office handling, news digest, file reading, and more; you can add custom skills. All data and tasks run on your machine; no third-party hosting." readme = "README.md" requires-python = ">=3.11,<3.14" dependencies = [ "agentscope==2.0.4.post1", "httpx>=0.27.0", "packaging>=24.0", "discord-py>=2.3", "dingtalk-stream>=0.24.3", "alibabacloud-dingtalk>=2.2.42", "alibabacloud-tea-openapi>=0.4.4", "alibabacloud-credentials>=0.3.0", "alibabacloud-tea-util>=0.3.0", "uvicorn>=0.40.0", "apscheduler>=3.11.2,<4", "playwright>=1.49.0", "questionary>=2.1.1", "mss>=9.0.0", "reme-ai==0.4.1.3", "transformers>=4.30.0", "python-dotenv>=1.0.0", "python-socks>=2.5.3", "onnxruntime<1.24", "lark-oapi>=1.5.3", "python-telegram-bot>=20.0", "slack-bolt>=1.22.0", "twilio>=9.10.2", "pywebview>=4.0", "aiofiles>=24.1.0", "paho-mqtt>=2.0.0", "wecom-aibot-python-sdk==1.0.2", "matrix-nio>=0.25.0", "shortuuid>=1.0.0", "google-genai>=1.67.0", "tzdata>=2024.1", "cryptography>=43.0.0", "keyring>=25.0.0", "pyyaml>=6.0", "wcmatch>=10.0", "json-repair>=0.30.0", "segno>=1.6.6", "modelscope>=1.35.0", "huggingface_hub>=0.20.0", "pillow>=10.0.0", "agent-client-protocol>=0.9.0,<0.11.0", # Streaming-markdown terminal UI for the bundled `qwenpaw` TUI # (v4+ adds the streaming Markdown widget). 8.2.8 fixes parsing of # multi-codepoint Kitty "associated text" so input methods (Chinese, # Japanese, accents, ...) no longer leak escape sequences into the prompt # (Textualize/textual#6592). Keep the temporary upper bound in sync with # the TUI compatibility shim for Textualize/textual#6643; remove both # after Textual ships and QwenPaw verifies the upstream fix. "textual>=8.2.8,<8.2.9", "psutil>=6.0.0", "openai>=2.0.0,<=2.33.0", # anyio 4.13.0: _deliver_cancellation busy-loop / getpid storm (QwenPaw#2632) "anyio>=4.0.0,<4.13.0", "watchfiles>=0.22", "orjson>=3.9", # Coding Mode — Python LSP server bundled as a zero-config fallback # so the `lsp` tool always works for .py files (see PROPOSAL §3.4). "python-lsp-server[all]>=1.10", # Coding Mode — multi-language AST pattern matcher used by ast_search. # Pure-Python wrapper around a prebuilt Rust binary; PyPI distributes # wheels for all three OSes. "ast-grep-cli>=0.20", "html2text>=2024.2.26", ] [project.urls] Homepage = "https://qwenpaw.agentscope.io/" Repository = "https://github.com/agentscope-ai/QwenPaw" Documentation = "https://qwenpaw.agentscope.io/docs/" Issues = "https://github.com/agentscope-ai/QwenPaw/issues" [tool.setuptools.dynamic] version = {attr = "pineagents.__version__.__version__"} [tool.setuptools] packages = { find = { where = ["src"] } } include-package-data = true [tool.setuptools.package-data] # Dockerfile copies console build output to src/pineagents/console/ (no dist subdir). "pineagents" = [ "console/**", "agents/md_files/**", "agents/skills/**", "agents/context/visual_compression/assets/atlas-gray.ts", "agents/context/visual_compression/assets/atlas-gray-medium.ts", "agents/context/visual_compression/assets/atlas-gray-high.ts", "agents/context/visual_compression/assets/JETBRAINS_MONO_LICENSE.txt", "agents/context/visual_compression/assets/UNIFONT_LICENSE.txt", "agents/context/visual_compression/assets/SPLEEN_LICENSE.txt", "agents/tools/deprecated_browser/skills/**", "tokenizer/**", "security/tool_guard/rules/**", "security/skill_scanner/rules/**", "security/skill_scanner/data/**", "browser/control_link/injected/*.js", "docs/*.md", "app/channels/yuanbao/proto/**", ] [build-system] requires = ["setuptools>=42", "wheel"] build-backend = "setuptools.build_meta" [project.scripts] # PineAgents 品牌命令;qwenpaw/copaw 为兼容别名。 pineagents = "pineagents.cli.main:cli" # Optional doctor plugins: callable (DoctorRunContext) -> list[str] # [project.entry-points."qwenpaw.doctor"] # my_pkg = "my_pkg.doctor:doctor_notes" # Legacy group "copaw.doctor" is still loaded when present. [project.optional-dependencies] test = [ "pytest>=8.3.5", "pytest-asyncio>=0.23.0", "pytest-cov>=6.2.1", "pytest-timeout>=2.3.0", "pytest-xdist>=3.5.0", "hypothesis>=6.0.0", "qoder-agent-sdk==1.0.9", ] dev = [ "pre-commit>=4.2.0", ] local = [ "huggingface_hub>=0.20.0", ] whisper = [ "openai-whisper>=20231117", ] codex = [ "openai-codex==0.144.4", ] qoder = [ "qoder-agent-sdk==1.0.9", ] full = [ "pineagents[local,whisper,codex,qoder]", ] sip = [ "pyVoIP>=1.6.0", "dashscope>=1.0.0", "dashscope-realtime>=0.1.0", "audioop-lts; python_version >= '3.13'", ] sip-livekit = [ "pineagents[sip]", "livekit>=1.0.0", "livekit-api>=0.6.0", ] [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", "p0: critical user flows (messaging, CRUD, global config, security); PR smoke gate", "p1: supported features (settings, scoped overrides, helpers); nightly regression", "p2: error paths, 404 handling, validation, contracts, metadata", "unit: marks tests as unit tests", "contract: marks tests as contract tests", "integration: marks tests as integration tests", "e2e: marks tests as end-to-end tests", ] testpaths = [ "tests", ] [tool.coverage.run] source = ["src/pineagents"] omit = [ "*/tests/*", "*/test_*", "*/__pycache__/*", ] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "pass", ] # Coverage gate (raised in stages per the July quality plan): # 30 (baseline) -> 45 (stage 1) -> 50 (current, ~1.6pt headroom under # CI's measured 51.59% per the "leave 1-2pt to resist flaky" rule). # Bump up only after natural coverage rises (bug-regression + contract # gains), never chase a number. fail_under = 50 show_missing = true [tool.coverage.html] directory = "htmlcov"