Skip to content

Commit ea3aaf7

Browse files
Merge pull request #180 from dashscope/dev/issues-5
Dev/issues 5
2 parents 6aec6b6 + 04e06fa commit ea3aaf7

18 files changed

Lines changed: 705 additions & 88 deletions

‎README.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,21 @@ The SDK ships with an interactive AI assistant, **DashScope SDK Expert**, built
107107

108108
For the latest model list, visit [Bailian Model Plaza](https://bailian.console.aliyun.com/).
109109

110+
## Shell Completion
111+
112+
Run the appropriate command once, then restart your shell (or re-source your config file):
113+
114+
| Shell | Install command |
115+
|-------|-----------------|
116+
| **bash** | `dashscope --install-completion bash` |
117+
| **zsh** | `dashscope --install-completion zsh` |
118+
| **fish** | `dashscope --install-completion fish` |
119+
120+
To preview the completion script without installing:
121+
```shell
122+
dashscope --show-completion bash
123+
```
124+
110125
## Logging
111126
To output Dashscope logs, you need to configure the logger.
112127
```shell

‎dashscope/acli/cli/constants.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@
225225
"/rule": ["list", "add", "remove", "edit", "clear"],
226226
"/profile": ["list", "search", "add", "remove", "clear"],
227227
"/memory": ["list", "search", "remove", "clear"],
228-
"/session": ["new", "list", "switch", "rename", "remove"],
228+
"/session": ["new", "list", "switch", "rename", "fork", "remove"],
229229
"/mcp": ["list", "add", "remove"],
230230
"/cron": ["add", "list", "remove", "pause", "resume"],
231231
"/feedback": ["good", "bad"],

‎dashscope/acli/cli/handlers_session.py‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
"""Session management command handlers."""
33
# pylint: disable=too-many-branches,too-many-statements,unused-argument
4+
# pylint: disable=too-many-return-statements
45

56
from __future__ import annotations
67

@@ -15,6 +16,8 @@
1516
" /session list — list all sessions\n"
1617
" /session switch <n> — switch to a topic\n"
1718
" /session rename <old> <new> — rename\n"
19+
" /session fork <new> [src] — fork a session (default src: "
20+
"current)\n"
1821
" /session remove <n> — remove session "
1922
"(default cannot be removed)\n"
2023
" /session scene — show scene memory of the current topic\n"
@@ -128,6 +131,35 @@ def _handle_session_command(cmd: str, config, agent) -> None:
128131
f"or '{new_name}' already exists[/red]",
129132
)
130133

134+
elif subcmd == "fork":
135+
if len(parts) < 3:
136+
console.print(
137+
"[dim]Usage: /session fork <new> [src][/dim]",
138+
)
139+
return
140+
fork_args = parts[2].split(maxsplit=1)
141+
dst = fork_args[0]
142+
src = (
143+
fork_args[1]
144+
if len(fork_args) > 1
145+
else (session_mgr.get_current_topic())
146+
)
147+
# Flush the live conversation when forking the active topic so
148+
# the fork carries the latest messages.
149+
if src == session_mgr.get_current_topic():
150+
if agent.session_path and agent.messages:
151+
agent.save_session()
152+
if session_mgr.fork_topic(src, dst):
153+
console.print(
154+
f"[green]Forked session: {src} → {dst}[/green]\n"
155+
f" [dim]Switch with: /session switch {dst}[/dim]",
156+
)
157+
else:
158+
console.print(
159+
f"[red]Fork failed: '{src}' does not exist "
160+
f"or '{dst}' already exists[/red]",
161+
)
162+
131163
elif subcmd == "remove":
132164
topic = parts[2] if len(parts) > 2 else ""
133165
if not topic:

‎dashscope/acli/cli/mcp.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,9 @@ async def _handle_mcp_command(cmd: str, config: Config):
149149
" /mcp — list connected services\n"
150150
" /mcp list — show Bailian available services\n"
151151
" /mcp add <svc> — add an MCP service\n"
152-
" /mcp remove <svc> — remove an MCP service[/dim]",
152+
" /mcp remove <svc> — remove an MCP service\n"
153+
"Stdio servers: add [[mcp_servers]] in config.toml with "
154+
'transport = "stdio", command and args[/dim]',
153155
)
154156

155157

‎dashscope/acli/commands.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
("/memory", "Chat history (list/search/remove <id|num>/clear)"),
113113
(
114114
"/session",
115-
"Session management (new/list/switch/rename/remove/scene)",
115+
"Sessions (new/list/switch/rename/fork/remove/scene)",
116116
),
117117
(
118118
"/summarize",

‎dashscope/acli/mcp_stdio.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
import asyncio
1414
import json
1515

16+
from dashscope.acli import __version__
1617
from dashscope.acli.platforms.bailian.mcp import MCP_PROTOCOL_VERSION, MCPError
1718

1819
__all__ = ["StdioMCPClient", "MCPError"]
1920

20-
_CLIENT_INFO = {"name": "acli", "version": "0.1.0"}
21+
_CLIENT_INFO = {"name": "acli", "version": __version__}
2122
_CLOSE_TIMEOUT = 3.0
2223
_STDERR_TAIL = 500
2324

‎dashscope/acli/session.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ def fork_topic(self, src: str, dst: str) -> bool:
274274
if not src_dir.exists() or dst_dir.exists():
275275
return False
276276
try:
277+
import shutil
278+
277279
dst_dir.mkdir(parents=True)
278280
self._save_meta(
279281
dst,
@@ -285,9 +287,12 @@ def fork_topic(self, src: str, dst: str) -> bool:
285287
)
286288
src_events = self._events_file(src)
287289
if src_events.exists():
288-
import shutil
289-
290290
shutil.copy2(src_events, self._events_file(dst))
291+
# Pre-snapshot sessions keep their messages only in
292+
# history.json; copy it too so the fork restores them.
293+
src_history = self._history_file(src)
294+
if src_history.exists():
295+
shutil.copy2(src_history, self._history_file(dst))
291296
except OSError:
292297
return False
293298
self.event_log(dst).append(

‎dashscope/acli/session_events.py‎

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,6 @@ def read(
130130
events.append(entry)
131131
return events
132132

133-
def tail(
134-
self,
135-
n: int,
136-
event_type: str | None = None,
137-
) -> list[dict[str, Any]]:
138-
"""Return the most recent ``n`` events (optionally by type)."""
139-
if n <= 0:
140-
return []
141-
return self.read(event_type)[-n:]
142-
143133
def read_raw(self) -> list[dict[str, Any]]:
144134
"""Return every well-formed entry, any schema version.
145135

0 commit comments

Comments
 (0)