Skip to content

Commit 2bcb88e

Browse files
Merge branch 'main' into dev/agent-rag-memory
2 parents 39b2d56 + 93af254 commit 2bcb88e

104 files changed

Lines changed: 23223 additions & 235 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/unit_test.yml‎

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,19 @@ jobs:
1515
runs-on: ${{ matrix.os }}
1616
strategy:
1717
matrix:
18-
os: [ ubuntu-24.04 ]
19-
python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
18+
# ubuntu-latest (26.04) ships no CPython 3.9 build, so pin the
19+
# still-supported 3.9 leg to 24.04 and keep the rest on latest.
20+
include:
21+
- os: ubuntu-24.04
22+
python-version: '3.9'
23+
- os: ubuntu-latest
24+
python-version: '3.10'
25+
- os: ubuntu-latest
26+
python-version: '3.11'
27+
- os: ubuntu-latest
28+
python-version: '3.12'
29+
- os: ubuntu-latest
30+
python-version: '3.13'
2031

2132
steps:
2233
- name: Checkout repository
@@ -68,8 +79,19 @@ jobs:
6879
runs-on: ${{ matrix.os }}
6980
strategy:
7081
matrix:
71-
os: [ ubuntu-24.04 ]
72-
python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
82+
# ubuntu-latest (26.04) ships no CPython 3.9 build, so pin the
83+
# still-supported 3.9 leg to 24.04 and keep the rest on latest.
84+
include:
85+
- os: ubuntu-24.04
86+
python-version: '3.9'
87+
- os: ubuntu-latest
88+
python-version: '3.10'
89+
- os: ubuntu-latest
90+
python-version: '3.11'
91+
- os: ubuntu-latest
92+
python-version: '3.12'
93+
- os: ubuntu-latest
94+
python-version: '3.13'
7395

7496
steps:
7597
- name: Checkout repository

‎README.md‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,26 @@ The SDK ships with an interactive AI assistant, **DashScope SDK Expert**, built
437437
- Install with the `acli` extra: `pip install "dashscope[acli]"`. Add `acli-voice` / `acli-camera` for voice and camera input, or `acli-all` for everything — see the [extras table](#installation).
438438
- Full walkthrough: [DashScope SDK Expert guide](https://help.aliyun.com/en/model-studio/dashscope-sdk-expert).
439439

440+
## Command line
441+
442+
`pip install -U dashscope` puts two independent commands on your `PATH`. `dashscope` serves the SDK-shaped **2.0** command tree; `dashscope1` serves the frozen **1.x** implementation:
443+
444+
| Entry point | Implementation | Examples |
445+
|-------------|----------------|----------|
446+
| `dashscope` | 2.0, following the SDK resource tree | `chat create`, `apps completions create`, `multimodal chat create`, `rl jobs create`, `rl functions register`, `images jobs create`, `audio asr transcribe`, `agentstudio sessions events send` |
447+
| `dashscope1` | 1.x, using the 1.x SDK | `generation call`, `application call`, `image-synthesis create`, `multimodal-conversation call`, `fine-tunes call`, `agentic-rl run`, `auth login`, `oss upload` |
448+
449+
The two CLI trees do not dispatch to or normalize arguments for each other. Running a 1.x-only command through `dashscope` exits with a usage error and points to `dashscope1`. Their module entry points are likewise independent:
450+
451+
```bash
452+
python -m dashscope.cli apps completions create ...
453+
python -m dashscope.legacy_1x.cli generation call ...
454+
```
455+
456+
Running `dashscope` with no arguments starts the [AI assistant](#ai-assistant-dashscope-sdk-expert) instead of the CLI.
457+
458+
For the complete 2.0 CLI command map, output formats, exit codes, configuration precedence and CI recipes, see the CLI section in [`examples/README.md`](examples/README.md).
459+
440460
## Shell completion
441461

442462
Run the command for your shell once, then restart the shell (or re-source your config):
@@ -453,6 +473,8 @@ Preview the script without installing:
453473
dashscope --show-completion bash
454474
```
455475

476+
Completion is installed through the 2.0 `dashscope` entry point.
477+
456478
## Logging
457479

458480
Set the level via settings or the environment:
@@ -475,10 +497,11 @@ examples/
475497
├── 02_advanced_engineering/ Mock debugging, semantic cache, circuit breaker + multi-region DR
476498
├── 03_agent_recipes/ Tool-call loop, RAG, MCP server, AgentStudio
477499
├── 04_real_world_scenarios/ End-to-end production harnesses (RAG, realtime meetings, customer service)
500+
├── 05_cli/ Offline CLI output/error and subprocess CI harnesses
478501
└── legacy_1x/ 1.x module-level API examples, for reference
479502
```
480503

481-
See [`examples/README.md`](examples/README.md). Several flagship cases run fully offline (mock transports) with no API key.
504+
See [`examples/README.md`](examples/README.md) for the full guide, including the complete CLI command map and shell/CI recipes. Several flagship cases and both CLI harnesses run fully offline with no API key.
482505

483506
## Migrating from 1.x
484507

@@ -496,6 +519,8 @@ The 1.x module-level API is unchanged and still supported — you can adopt 2.0
496519
| `dashscope.set_region(region, workspace_id)` | `dashscope.Client(region=..., workspace=...)` |
497520
| OpenAI-compatible via `dashscope.aigc.chat_completion.Completions` | `dashscope.Client(protocol="openai")` |
498521

522+
The CLI follows the same split — see [Command line](#command-line) above.
523+
499524
### Package layout and compatibility
500525

501526
The 2.0 implementation sits directly under `dashscope`; the former `dashscope.v2` namespace is gone. AgentStudio and FineTune/Agentic RL each have a single business core under `dashscope.applications`, with two thin public facades on top:

‎README_zh.md‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,26 @@ SDK 内置了交互式 AI 助手 **DashScope SDK Expert**,基于随包提供
437437
- 通过 `acli` extra 安装:`pip install "dashscope[acli]"`。需要语音/摄像头输入可加装 `acli-voice` / `acli-camera`,或直接用 `acli-all` 装齐 —— 详见[安装](#安装)一节的 extra 表格。
438438
- 完整使用指南:[DashScope SDK Expert 文档](https://help.aliyun.com/zh/model-studio/dashscope-sdk-expert)。
439439

440+
## 命令行
441+
442+
`pip install -U dashscope` 会安装两个相互独立的命令。`dashscope` 提供按 SDK 资源树设计的 **2.0** 命令;`dashscope1` 提供冻结的 **1.x** 实现:
443+
444+
| 入口 | 实现 | 示例 |
445+
|------|------|------|
446+
| `dashscope` | 2.0,对齐 SDK 资源树 | `chat create`、`apps completions create`、`multimodal chat create`、`rl jobs create`、`rl functions register`、`images jobs create`、`audio asr transcribe`、`agentstudio sessions events send` |
447+
| `dashscope1` | 1.x,调用 1.x SDK | `generation call`、`application call`、`image-synthesis create`、`multimodal-conversation call`、`fine-tunes call`、`agentic-rl run`、`auth login`、`oss upload` |
448+
449+
两套 CLI 不会相互分发命令或转换参数。通过 `dashscope` 运行 1.x 专有命令会返回用法错误,并提示改用 `dashscope1`。两者的模块入口也相互独立:
450+
451+
```bash
452+
python -m dashscope.cli apps completions create ...
453+
python -m dashscope.legacy_1x.cli generation call ...
454+
```
455+
456+
不带参数运行 `dashscope` 会启动 [AI 助手](#ai-助手dashscope-sdk-expert),而不是 CLI。
457+
458+
完整的 2.0 CLI 命令地图、输出格式、退出码、配置优先级和 CI 配方,见 [`examples/README_zh.md`](examples/README_zh.md) 的命令行章节。
459+
440460
## Shell 命令补全
441461

442462
针对你的 Shell 运行一次对应命令,然后重启 Shell(或重新 source 配置文件):
@@ -453,6 +473,8 @@ SDK 内置了交互式 AI 助手 **DashScope SDK Expert**,基于随包提供
453473
dashscope --show-completion bash
454474
```
455475

476+
命令补全通过 2.0 的 `dashscope` 入口安装。
477+
456478
## 日志
457479

458480
通过设置或环境变量配置日志级别:
@@ -475,10 +497,11 @@ examples/
475497
├── 02_advanced_engineering/ 本地 mock 调试、语义缓存、熔断 + 多地域容灾
476498
├── 03_agent_recipes/ 工具调用循环、RAG、MCP server、AgentStudio
477499
├── 04_real_world_scenarios/ 端到端生产级 harness(RAG、实时会议、智能客服)
500+
├── 05_cli/ 离线 CLI 输出/错误契约与子进程 CI 示例
478501
└── legacy_1x/ 1.x 模块级 API 示例,仅供参考
479502
```
480503

481-
详见 [`examples/README_zh.md`](examples/README_zh.md)。其中若干旗舰案例可完全离线运行(mock 传输),无需 API Key。
504+
完整指南见 [`examples/README_zh.md`](examples/README_zh.md),其中包含 CLI 命令地图和 shell/CI 配方。若干旗舰案例与两个 CLI 示例都可完全离线运行,无需 API Key。
482505

483506
## 从 1.x 迁移
484507

@@ -496,6 +519,8 @@ examples/
496519
| `dashscope.set_region(region, workspace_id)` | `dashscope.Client(region=..., workspace=...)` |
497520
| OpenAI 兼容通过 `dashscope.aigc.chat_completion.Completions` | `dashscope.Client(protocol="openai")` |
498521

522+
CLI 也遵循同样的拆分 —— 见上方[命令行](#命令行)一节。
523+
499524
### 包布局与兼容策略
500525

501526
2.0 实现直接位于 `dashscope` 根包,原 `dashscope.v2` 命名空间已移除。

‎dashscope/__init__.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ def set_region(region: str, workspace_id: str = None):
166166
"applications",
167167
"assistants",
168168
"audio",
169-
"cli",
170169
"common",
171170
"embeddings",
172171
"files",

‎dashscope/_shared/_sdk_ident.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
(``dashscope/<version>; python/...; platform/...; processor/...``) and is
2727
deliberately not shared with the 2.0 transport's own
2828
``dashscope.transport.http.default_user_agent()``
29-
(``dashscope-v2-python/<version>``). Those are two distinct backend
29+
(``dashscope-sdk-python/<version>``). Those are two distinct backend
3030
contracts, not two spellings of one value, so they must not be merged.
3131
3232
Only the stdlib is imported at module level; ``dashscope.version`` is

‎dashscope/acli/expert.py‎

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# -*- coding: utf-8 -*-
2+
"""Shared DashScope SDK Expert adapter for both console entry points."""
3+
4+
import sys
5+
from pathlib import Path
6+
7+
from rich.console import Console
8+
9+
import dashscope
10+
11+
err_console = Console(stderr=True)
12+
13+
_MD_MARKER = "<!-- managed-by: dashscope-expert -->"
14+
_PY_MARKER = "# managed-by: dashscope-expert"
15+
_EXPERT_EXAMPLE = "dashscope-sdk-expert"
16+
17+
18+
def _cleanup_legacy_expert_sync():
19+
"""Remove files the deleted expert bundling synced into ~/.acli.
20+
21+
Only files carrying the managed marker are deleted — without it the file
22+
is user-owned and left untouched. Needed so stale global copies don't
23+
shadow the workspace ./.acli/ configs installed via example download.
24+
"""
25+
try:
26+
from dashscope.acli.config import CONFIG_DIR
27+
except ImportError:
28+
return
29+
md_targets = []
30+
for subdir in ("skills", "references"):
31+
target_dir = CONFIG_DIR / subdir
32+
if target_dir.is_dir():
33+
md_targets.extend(target_dir.glob("*.md"))
34+
for path in md_targets:
35+
try:
36+
if _MD_MARKER in path.read_text(encoding="utf-8"):
37+
path.unlink()
38+
except OSError:
39+
pass
40+
build = CONFIG_DIR / "build_sdk_index.py"
41+
try:
42+
if build.is_file() and _PY_MARKER in build.read_text(encoding="utf-8"):
43+
build.unlink()
44+
except OSError:
45+
pass
46+
47+
48+
def _maybe_offer_example_download():
49+
"""First interactive run without ./.acli: offer the SDK-expert example.
50+
51+
Accepting merges the example into ./.acli/ via the same code path as
52+
`example download` (copied from the packaged install dir when present);
53+
declining writes a marker into ./.acli/ so we never ask again here.
54+
"""
55+
if not sys.stdin.isatty() or (Path.cwd() / ".acli").is_dir():
56+
return
57+
try:
58+
from dashscope.acli.cli.examples import _handle_example_command
59+
from dashscope.acli.cli.handlers_key import _GUIDE_DOC, _doc_locale
60+
except ImportError:
61+
return
62+
err_console.print(
63+
"[cyan]First run:[/cyan] download the dashscope-sdk-expert "
64+
"example config into ./.acli/\n"
65+
"(SDK Q&A expert persona + skill templates + SDK knowledge "
66+
"index; pure config, editable anytime).",
67+
)
68+
err_console.print(
69+
f"[dim]Guide: {_GUIDE_DOC.format(_doc_locale())}[/dim]",
70+
)
71+
try:
72+
answer = input("Download the example config? [Y/n] ").strip().lower()
73+
except (EOFError, KeyboardInterrupt):
74+
err_console.print()
75+
return
76+
if answer in ("n", "no"):
77+
try:
78+
marker = Path.cwd() / ".acli" / ".dashscope-example-declined"
79+
marker.parent.mkdir(parents=True, exist_ok=True)
80+
marker.write_text("declined\n", encoding="utf-8")
81+
except OSError:
82+
pass
83+
err_console.print(
84+
"[dim]Skipped. To customize later, run: "
85+
"python -m dashscope.acli example download "
86+
"dashscope-sdk-expert[/dim]",
87+
)
88+
return
89+
_handle_example_command(["download", _EXPERT_EXAMPLE])
90+
91+
92+
def _route_to_expert(command, tui=None):
93+
"""Run the vendored acli agent (bare ``dashscope`` or ``dashscope expert``).
94+
95+
``command`` is a one-shot prompt, or None for the interactive REPL.
96+
"""
97+
try:
98+
from dashscope.acli.cli.handlers_key import _GUIDE_DOC, _doc_locale
99+
from dashscope.acli.ui.embedded import run
100+
except ImportError as exception:
101+
err_console.print(
102+
"[yellow]Tip:[/yellow] Install dashscope[acli] to enable "
103+
"the agent "
104+
f"({exception}).",
105+
)
106+
return
107+
108+
if command is None and not sys.stdin.isatty():
109+
# The interactive REPL needs a real terminal; prompt_toolkit crashes
110+
# on non-tty stdin (e.g. kqueue rejects /dev/null with EINVAL).
111+
# Treat piped text as a one-shot prompt instead.
112+
try:
113+
piped = sys.stdin.read().strip()
114+
except OSError:
115+
piped = ""
116+
if not piped:
117+
err_console.print(
118+
"[red]Error:[/red] Interactive mode requires a terminal. "
119+
'Pass a prompt instead, e.g. dashscope expert "your question".',
120+
)
121+
sys.exit(2)
122+
command = piped
123+
124+
_cleanup_legacy_expert_sync()
125+
if command is None:
126+
_maybe_offer_example_download()
127+
128+
try:
129+
run(
130+
app_name="DashScope SDK Expert",
131+
prompt_symbol="dashscope> ",
132+
api_key=dashscope.api_key or None,
133+
command=command,
134+
tui=tui,
135+
module="expert",
136+
guide_url=_GUIDE_DOC.format(_doc_locale()),
137+
)
138+
except SystemExit:
139+
pass
140+
except Exception as exception: # pylint: disable=broad-except
141+
err_console.print(
142+
f"[yellow]Tip:[/yellow] Agent failed to start ({exception}).",
143+
)

‎dashscope/cli/__init__.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) Alibaba, Inc. and its affiliates.
3+
"""The dashscope CLI (v2).
4+
5+
Deliberately empty. ``import dashscope.cli`` runs for shell completion and
6+
``--help``, so it must not pull in the router, Typer, or the SDK.
7+
8+
There is no ``main`` re-export here on purpose: :mod:`dashscope.cli.main`
9+
is a submodule, and binding the same name on the package would make
10+
``from dashscope.cli import main`` resolve to a function or a module
11+
depending on import order. The console script names the module directly
12+
(``dashscope.cli.main:main``).
13+
"""

‎dashscope/cli/__main__.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) Alibaba, Inc. and its affiliates.
3+
"""``python -m dashscope.cli``."""
4+
5+
from dashscope.cli.main import main
6+
7+
if __name__ == "__main__":
8+
main()

0 commit comments

Comments
 (0)