mindcode 0.2.0__py3-none-any.whl → 0.3.2__py3-none-any.whl

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.
Files changed (74) hide show
  1. mindcode/_version.py +1 -1
  2. mindcode/approval.py +30 -5
  3. mindcode/bench/adapters/terminal_bench.py +6 -2
  4. mindcode/cli/__init__.py +14 -9
  5. mindcode/cli/commands/chat.py +2 -2
  6. mindcode/cli/commands/shell.py +16 -7
  7. mindcode/cli/shell/completion.py +2 -5
  8. mindcode/cli/shell/repl.py +284 -17
  9. mindcode/cli/shell/slash.py +199 -116
  10. mindcode/cli/shell/startup.py +2 -1
  11. mindcode/cli/shell/tui.py +37 -14
  12. mindcode/policy.py +100 -36
  13. mindcode/render.py +105 -52
  14. mindcode/runtime.py +68 -69
  15. mindcode-0.3.2.dist-info/METADATA +351 -0
  16. mindcode-0.3.2.dist-info/RECORD +63 -0
  17. mindcode/__pycache__/__init__.cpython-313.pyc +0 -0
  18. mindcode/__pycache__/__main__.cpython-313.pyc +0 -0
  19. mindcode/__pycache__/_version.cpython-313.pyc +0 -0
  20. mindcode/__pycache__/config.cpython-313.pyc +0 -0
  21. mindcode/__pycache__/policy.cpython-313.pyc +0 -0
  22. mindcode/__pycache__/remote.cpython-313.pyc +0 -0
  23. mindcode/__pycache__/render.cpython-313.pyc +0 -0
  24. mindcode/__pycache__/runtime.cpython-313.pyc +0 -0
  25. mindcode/__pycache__/tasking.cpython-313.pyc +0 -0
  26. mindcode/__pycache__/terminal_core.cpython-313.pyc +0 -0
  27. mindcode/bench/__pycache__/__init__.cpython-313.pyc +0 -0
  28. mindcode/bench/__pycache__/fake_tools.cpython-313.pyc +0 -0
  29. mindcode/bench/__pycache__/jsonutil.cpython-313.pyc +0 -0
  30. mindcode/bench/__pycache__/paths.cpython-313.pyc +0 -0
  31. mindcode/bench/__pycache__/predictions.cpython-313.pyc +0 -0
  32. mindcode/bench/__pycache__/report.cpython-313.pyc +0 -0
  33. mindcode/bench/__pycache__/runner.cpython-313.pyc +0 -0
  34. mindcode/bench/__pycache__/schema.cpython-313.pyc +0 -0
  35. mindcode/bench/__pycache__/trace.cpython-313.pyc +0 -0
  36. mindcode/bench/__pycache__/workspace.cpython-313.pyc +0 -0
  37. mindcode/bench/adapters/__pycache__/__init__.cpython-313.pyc +0 -0
  38. mindcode/bench/adapters/__pycache__/base.cpython-313.pyc +0 -0
  39. mindcode/bench/adapters/__pycache__/mini_bfcl.cpython-313.pyc +0 -0
  40. mindcode/bench/adapters/__pycache__/mini_gaia.cpython-313.pyc +0 -0
  41. mindcode/bench/adapters/__pycache__/mini_terminal.cpython-313.pyc +0 -0
  42. mindcode/bench/adapters/__pycache__/swe_bench.cpython-313.pyc +0 -0
  43. mindcode/bench/adapters/__pycache__/terminal_bench.cpython-313.pyc +0 -0
  44. mindcode/bench/scorers/__pycache__/base.cpython-313.pyc +0 -0
  45. mindcode/bench/scorers/__pycache__/composite.cpython-313.pyc +0 -0
  46. mindcode/bench/scorers/__pycache__/exact.cpython-313.pyc +0 -0
  47. mindcode/bench/scorers/__pycache__/json_call.cpython-313.pyc +0 -0
  48. mindcode/bench/scorers/__pycache__/swe.cpython-313.pyc +0 -0
  49. mindcode/bench/scorers/__pycache__/terminal.cpython-313.pyc +0 -0
  50. mindcode/bench/scorers/__pycache__/terminal_bench.cpython-313.pyc +0 -0
  51. mindcode/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  52. mindcode/cli/__pycache__/_shared.cpython-313.pyc +0 -0
  53. mindcode/cli/commands/__pycache__/__init__.cpython-313.pyc +0 -0
  54. mindcode/cli/commands/__pycache__/bench.cpython-313.pyc +0 -0
  55. mindcode/cli/commands/__pycache__/chat.cpython-313.pyc +0 -0
  56. mindcode/cli/commands/__pycache__/config_cmd.cpython-313.pyc +0 -0
  57. mindcode/cli/commands/__pycache__/remote.cpython-313.pyc +0 -0
  58. mindcode/cli/commands/__pycache__/shell.cpython-313.pyc +0 -0
  59. mindcode/cli/commands/__pycache__/status.cpython-313.pyc +0 -0
  60. mindcode/cli/commands/__pycache__/task.cpython-313.pyc +0 -0
  61. mindcode/cli/commands/__pycache__/terminal.cpython-313.pyc +0 -0
  62. mindcode/cli/shell/__pycache__/__init__.cpython-313.pyc +0 -0
  63. mindcode/cli/shell/__pycache__/completion.cpython-313.pyc +0 -0
  64. mindcode/cli/shell/__pycache__/menu.cpython-313.pyc +0 -0
  65. mindcode/cli/shell/__pycache__/repl.cpython-313.pyc +0 -0
  66. mindcode/cli/shell/__pycache__/slash.cpython-313.pyc +0 -0
  67. mindcode/cli/shell/__pycache__/startup.cpython-313.pyc +0 -0
  68. mindcode/terminal/__pycache__/__init__.cpython-313.pyc +0 -0
  69. mindcode/terminal/__pycache__/__main__.cpython-313.pyc +0 -0
  70. mindcode-0.2.0.dist-info/METADATA +0 -244
  71. mindcode-0.2.0.dist-info/RECORD +0 -116
  72. {mindcode-0.2.0.dist-info → mindcode-0.3.2.dist-info}/WHEEL +0 -0
  73. {mindcode-0.2.0.dist-info → mindcode-0.3.2.dist-info}/entry_points.txt +0 -0
  74. {mindcode-0.2.0.dist-info → mindcode-0.3.2.dist-info}/top_level.txt +0 -0
mindcode/_version.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """mindcode 版本与品牌信息。"""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.1"
4
4
 
5
5
  __logo__ = r"""
6
6
  [bold cyan] _ _[/bold cyan]
mindcode/approval.py CHANGED
@@ -9,12 +9,13 @@ one-shot / TUI 未启动时回退到 ``menu.prompt_yes_no``。
9
9
  from __future__ import annotations
10
10
 
11
11
  import json
12
+ import time
12
13
  from collections.abc import Awaitable, Callable
13
14
  from typing import Any
14
15
 
15
16
  from mindagent.core import ActionRequest, AgentContext
16
17
 
17
- from .policy import ApprovalCallback
18
+ from .policy import ApprovalCallback, FileAccessCallback
18
19
 
19
20
 
20
21
  def risk_label(risk: Any) -> str:
@@ -47,10 +48,7 @@ def describe_action(action: ActionRequest) -> str:
47
48
  return f"{verb} {path} [{risk_label(action.risk)}]"
48
49
  if name == "exec_command":
49
50
  command = arguments.get("command", "")
50
- if isinstance(command, list):
51
- preview = " ".join(_one_line(item) for item in command)
52
- else:
53
- preview = _one_line(command)
51
+ preview = _one_line(command) if isinstance(command, str) else ""
54
52
  if len(preview) > 120:
55
53
  preview = preview[:117] + "..."
56
54
  return f"Command {preview} [{risk_label(action.risk)}]"
@@ -103,3 +101,30 @@ def make_shell_approval(
103
101
  )
104
102
 
105
103
  return _approve
104
+
105
+
106
+ def make_shell_file_access_approval(
107
+ get_chooser: Callable[[], Chooser | None],
108
+ ) -> FileAccessCallback:
109
+ """Ask for a precise, single-call external read using a bound decision."""
110
+ from mindagent.core import ExternalFileReadDecision
111
+
112
+ async def approve(context, request):
113
+ title = (
114
+ "允许读取 workspace 外部文件?\n"
115
+ f"精确文件:{request.path}\n"
116
+ "权限:只读;范围:仅此次工具调用(一次),不扩大 workspace。\n"
117
+ f"有效期:剩余 {max(0, int(request.expires_at - time.time()))} 秒,过期需重新请求。"
118
+ )
119
+ chooser = get_chooser()
120
+ if chooser is not None:
121
+ result = await chooser(
122
+ title, [("allow", "允许此次只读访问"), ("deny", "拒绝")], "deny",
123
+ )
124
+ approved = result == "allow"
125
+ else:
126
+ from .cli.shell.menu import prompt_yes_no
127
+ approved = await prompt_yes_no(title, default_yes=False)
128
+ return ExternalFileReadDecision(request_id=request.request_id, approved=approved)
129
+
130
+ return approve
@@ -4,8 +4,6 @@ import json
4
4
  from pathlib import Path
5
5
  from typing import Any
6
6
 
7
- import yaml
8
-
9
7
  from ..paths import DEFAULT_TERMINAL_BENCH_ROOT
10
8
  from ..schema import BenchmarkCase, BenchmarkFile
11
9
  from ..scorers.base import Scorer
@@ -52,6 +50,12 @@ def _case_from_json(raw: dict[str, Any]) -> BenchmarkCase:
52
50
 
53
51
 
54
52
  def _case_from_task_dir(task_dir: Path) -> BenchmarkCase:
53
+ try:
54
+ import yaml
55
+ except ImportError as exc:
56
+ raise RuntimeError(
57
+ "terminal_bench 需要 pyyaml,请先 pip install pyyaml"
58
+ ) from exc
55
59
  task = yaml.safe_load((task_dir / "task.yaml").read_text(encoding="utf-8"))
56
60
  files = tuple(_iter_visible_files(task_dir))
57
61
  instruction = str(task["instruction"])
mindcode/cli/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
  cli/__init__.py typer app + 命令注册
5
5
  cli/_shared.py 共享 console + find_config_file
6
6
  cli/commands/
7
- shell.py `mindcode shell`(默认子命令)
7
+ shell.py 顶层 `mindcode` 默认入口 handler
8
8
  chat.py `mindcode chat -m "..."`
9
9
  task.py `mindcode task run/list/status/tail`
10
10
  status.py `mindcode status`
@@ -20,12 +20,12 @@
20
20
  from __future__ import annotations
21
21
 
22
22
  import typer
23
+ from click import UsageError
23
24
 
24
25
  from .._version import __version__
25
26
  from ._shared import console
26
27
 
27
- KNOWN_SUBCOMMANDS = {
28
- "shell",
28
+ PUBLIC_SUBCOMMANDS = {
29
29
  "chat",
30
30
  "status",
31
31
  "config",
@@ -37,21 +37,25 @@ KNOWN_SUBCOMMANDS = {
37
37
 
38
38
 
39
39
  class DefaultShellGroup(typer.core.TyperGroup):
40
- """让 `mindcode`(不带子命令)默认进 shell。
40
+ """让顶层 `mindcode` 直接复用内部 Shell 参数解析。
41
41
 
42
- 当第一个非 flag 参数不是已知子命令时,把 "shell" 注入到 args 前面,
43
- 让 click 走完整的参数解析路径。
42
+ 公开子命令保持原分派;其他参数注入隐藏的 ``shell`` handler。
44
43
  """
45
44
 
46
45
  def parse_args(self, ctx, args):
47
46
  if args:
48
47
  first = args[0]
48
+ if first == "shell":
49
+ raise UsageError(
50
+ "`mindcode shell` 已移除;请改用 "
51
+ "`mindcode [PROMPT] [OPTIONS]`"
52
+ )
49
53
  if (
50
- first in KNOWN_SUBCOMMANDS
54
+ first in PUBLIC_SUBCOMMANDS
51
55
  or first in {"--help", "-h", "--version", "-v"}
52
56
  ):
53
57
  return super().parse_args(ctx, args)
54
- # 无子命令或第一参数是 shell 的 flag/位置参数 → 注入 shell
58
+ # 无公开子命令:交给隐藏的顶层 Shell handler 做完整参数解析。
55
59
  new_args = ["shell", *args]
56
60
  return super().parse_args(ctx, new_args)
57
61
 
@@ -98,7 +102,8 @@ from .commands.status import status # noqa: E402
98
102
  from .commands.task import app as task_app # noqa: E402
99
103
  from .commands.terminal import app as terminal_app # noqa: E402
100
104
 
101
- app.command("shell")(shell)
105
+ # 仅供 DefaultShellGroup 内部分派;不作为公开子命令展示。
106
+ app.command("shell", hidden=True)(shell)
102
107
  app.command()(chat)
103
108
  app.command()(status)
104
109
  app.add_typer(config_app, name="config")
@@ -44,10 +44,10 @@ def chat(
44
44
  None, "--max-steps", help="最大 step 数(默认 50)"
45
45
  ),
46
46
  step_timeout: float | None = typer.Option(
47
- None, "--step-timeout", help="单步超时秒数,0 表示禁用(默认 120)"
47
+ None, "--step-timeout", help="单步超时秒数,0 表示禁用(默认 300)"
48
48
  ),
49
49
  total_timeout: float | None = typer.Option(
50
- None, "--total-timeout", help="总超时秒数,0 表示禁用(默认 600)"
50
+ None, "--total-timeout", help="总超时秒数,0 表示禁用(默认 1800)"
51
51
  ),
52
52
  ) -> None:
53
53
  """发送单条消息,不进入交互模式。"""
@@ -1,4 +1,4 @@
1
- """`mindcode shell` 子命令 —— 交互式 REPL 入口。"""
1
+ """顶层 `mindcode` 默认入口的交互式 REPL handler。"""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -59,13 +59,15 @@ def shell(
59
59
  None, "--max-steps", help="最大 step 数(默认 50)"
60
60
  ),
61
61
  step_timeout: float | None = typer.Option(
62
- None, "--step-timeout", help="单步超时秒数,0 表示禁用(默认 120)"
62
+ None, "--step-timeout", help="单步超时秒数,0 表示禁用(默认 300)"
63
63
  ),
64
64
  total_timeout: float | None = typer.Option(
65
- None, "--total-timeout", help="总超时秒数,0 表示禁用(默认 600)"
65
+ None,
66
+ "--total-timeout",
67
+ help="总超时秒数,0 表示禁用(交互默认禁用;一次性/子代理默认 1800)",
66
68
  ),
67
69
  ) -> None:
68
- """启动交互式 shell(默认子命令)。"""
70
+ """启动顶层 `mindcode` 交互或 one-shot 模式。"""
69
71
  ws = Path(workspace).expanduser().resolve()
70
72
  if not ws.is_dir():
71
73
  console.print(
@@ -83,6 +85,15 @@ def shell(
83
85
  )
84
86
  raise typer.Exit(2)
85
87
 
88
+ if total_timeout == 0 or (
89
+ total_timeout is None and prompt is None and not subagents
90
+ ):
91
+ selected_total_timeout = None
92
+ else:
93
+ selected_total_timeout = (
94
+ total_timeout if total_timeout is not None else 1800.0
95
+ )
96
+
86
97
  try:
87
98
  rc = run_shell(
88
99
  ws,
@@ -98,9 +109,7 @@ def shell(
98
109
  step_timeout_s=None
99
110
  if step_timeout == 0
100
111
  else (step_timeout if step_timeout is not None else 300.0),
101
- total_timeout_s=None
102
- if total_timeout == 0
103
- else (total_timeout if total_timeout is not None else 1800.0),
112
+ total_timeout_s=selected_total_timeout,
104
113
  )
105
114
  except ValueError as exc:
106
115
  console.print(f"[red]配置错误:[/red] {exc}")
@@ -10,11 +10,8 @@ SLASH_COMMANDS = {
10
10
  "models": "切换当前模型",
11
11
  "compact": "压缩整理当前会话上下文",
12
12
  "permissions": "切换权限模式",
13
- "status": "显示当前会话状态",
14
- "config": "显示配置",
15
- "sessions": "列出本地会话",
16
- "history": "打印当前会话消息",
17
- "diff": "显示最后一次 diff",
13
+ "status": "查看当前历史 session 状态与上下文使用",
14
+ "resume": "恢复本地保存的历史 session",
18
15
  "clear": "清空当前会话历史",
19
16
  "help": "显示帮助",
20
17
  "exit": "退出",