dais-shell 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {dais_shell-0.2.0 → dais_shell-0.3.0}/PKG-INFO +1 -1
- {dais_shell-0.2.0 → dais_shell-0.3.0}/pyproject.toml +1 -1
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/__init__.py +8 -4
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/runtimes/BaseShellRuntime.py +4 -3
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/runtimes/BashRuntime.py +9 -4
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/runtimes/PowershellRuntime.py +48 -5
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/types/__init__.py +1 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/types/command_step.py +1 -0
- dais_shell-0.3.0/src/dais_shell/types/shell_script.py +17 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/README.md +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/constants.py +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/env_builder.py +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/iostream_reader.py +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/py.typed +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/runtimes/__init__.py +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/types/exceptions.py +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/utils/__init__.py +0 -0
- {dais_shell-0.2.0 → dais_shell-0.3.0}/src/dais_shell/utils/env_expander.py +0 -0
|
@@ -5,7 +5,9 @@ from typing import TypeAlias
|
|
|
5
5
|
from .env_builder import EnvBuilder
|
|
6
6
|
from .iostream_reader import IOStreamReaderResult, IOStreamReaderStatus
|
|
7
7
|
from .runtimes import BaseShellRuntime, BashRuntime, PowerShellRuntime
|
|
8
|
-
from .types import CommandStep
|
|
8
|
+
from .types.command_step import CommandStep
|
|
9
|
+
from .types.shell_script import ShellScript
|
|
10
|
+
from .types.exceptions import ShellError, ShellRuntimeNotFoundError, ForbiddenShellTargetError
|
|
9
11
|
from .constants import DEFAULT_COMMAND_BLACKLIST
|
|
10
12
|
|
|
11
13
|
ShellResult: TypeAlias = IOStreamReaderResult
|
|
@@ -30,19 +32,20 @@ class AgentShell:
|
|
|
30
32
|
return BashRuntime(max_lines)
|
|
31
33
|
|
|
32
34
|
def run_sync(self,
|
|
33
|
-
step: CommandStep,
|
|
35
|
+
step: CommandStep | ShellScript,
|
|
34
36
|
on_stdout=None,
|
|
35
37
|
on_stderr=None
|
|
36
38
|
) -> ShellResult:
|
|
37
39
|
return asyncio.run(self.run(step, on_stdout, on_stderr))
|
|
38
40
|
|
|
39
41
|
async def run(self,
|
|
40
|
-
step: CommandStep,
|
|
42
|
+
step: CommandStep | ShellScript,
|
|
41
43
|
on_stdout=None,
|
|
42
44
|
on_stderr=None
|
|
43
45
|
) -> ShellResult:
|
|
44
46
|
step = replace(step)
|
|
45
|
-
step
|
|
47
|
+
if isinstance(step, CommandStep):
|
|
48
|
+
step.validate_forbidden(self._command_blacklist)
|
|
46
49
|
step.env = (self._env_builder
|
|
47
50
|
.with_extra(step.env or {})
|
|
48
51
|
.build())
|
|
@@ -51,6 +54,7 @@ class AgentShell:
|
|
|
51
54
|
__all__ = [
|
|
52
55
|
"AgentShell",
|
|
53
56
|
"CommandStep",
|
|
57
|
+
"ShellScript",
|
|
54
58
|
"ShellResult",
|
|
55
59
|
"ShellResultStatus",
|
|
56
60
|
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from ..types import CommandStep
|
|
2
|
+
from ..types.command_step import CommandStep
|
|
3
|
+
from ..types.shell_script import ShellScript
|
|
3
4
|
from ..iostream_reader import IOStreamReaderResult
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class BaseShellRuntime(ABC):
|
|
7
8
|
@abstractmethod
|
|
8
9
|
def run_sync(self,
|
|
9
|
-
step: CommandStep,
|
|
10
|
+
step: CommandStep | ShellScript,
|
|
10
11
|
on_stdout=None,
|
|
11
12
|
on_stderr=None,
|
|
12
13
|
) -> IOStreamReaderResult: ...
|
|
13
14
|
|
|
14
15
|
@abstractmethod
|
|
15
16
|
async def run(self,
|
|
16
|
-
step: CommandStep,
|
|
17
|
+
step: CommandStep | ShellScript,
|
|
17
18
|
on_stdout=None,
|
|
18
19
|
on_stderr=None
|
|
19
20
|
) -> IOStreamReaderResult: ...
|
|
@@ -5,7 +5,9 @@ from dataclasses import asdict, dataclass
|
|
|
5
5
|
|
|
6
6
|
from dais_shell.utils.env_expander import EnvExpander
|
|
7
7
|
from .BaseShellRuntime import BaseShellRuntime
|
|
8
|
-
from ..types import CommandStep
|
|
8
|
+
from ..types.command_step import CommandStep
|
|
9
|
+
from ..types.shell_script import ShellScript
|
|
10
|
+
from ..types.exceptions import ShellRuntimeNotFoundError
|
|
9
11
|
from ..iostream_reader import IOStreamReader, IOStreamReaderResult
|
|
10
12
|
|
|
11
13
|
|
|
@@ -39,21 +41,24 @@ class BashRuntime(BaseShellRuntime):
|
|
|
39
41
|
step.to_wrapper_script(),
|
|
40
42
|
]
|
|
41
43
|
|
|
42
|
-
def _prepare_cmd(self, step: CommandStep) -> list[str]:
|
|
44
|
+
def _prepare_cmd(self, step: CommandStep | ShellScript) -> list[str]:
|
|
45
|
+
if isinstance(step, ShellScript):
|
|
46
|
+
return [self._shell, "-c", step.script]
|
|
47
|
+
|
|
43
48
|
env_expander = EnvExpander(step.env or {})
|
|
44
49
|
step.args = env_expander.expand(step.args)
|
|
45
50
|
step = BashCommandStep.from_command_step(step)
|
|
46
51
|
return self._make_bash_commands(step)
|
|
47
52
|
|
|
48
53
|
def run_sync(self,
|
|
49
|
-
step: CommandStep,
|
|
54
|
+
step: CommandStep | ShellScript,
|
|
50
55
|
on_stdout=None,
|
|
51
56
|
on_stderr=None,
|
|
52
57
|
) -> IOStreamReaderResult:
|
|
53
58
|
return asyncio.run(self.run(step, on_stdout, on_stderr))
|
|
54
59
|
|
|
55
60
|
async def run(self,
|
|
56
|
-
step: CommandStep,
|
|
61
|
+
step: CommandStep | ShellScript,
|
|
57
62
|
on_stdout=None,
|
|
58
63
|
on_stderr=None
|
|
59
64
|
) -> IOStreamReaderResult:
|
|
@@ -5,12 +5,49 @@ import shutil
|
|
|
5
5
|
import re
|
|
6
6
|
import xml.etree.ElementTree as ET
|
|
7
7
|
import subprocess
|
|
8
|
-
from dataclasses import asdict, dataclass
|
|
8
|
+
from dataclasses import asdict, dataclass, fields
|
|
9
9
|
|
|
10
10
|
from dais_shell.utils.env_expander import EnvExpander
|
|
11
11
|
from .BaseShellRuntime import BaseShellRuntime
|
|
12
12
|
from ..iostream_reader import IOStreamReader, IOStreamReaderResult
|
|
13
|
-
from ..types import CommandStep
|
|
13
|
+
from ..types.command_step import CommandStep
|
|
14
|
+
from ..types.shell_script import ShellScript
|
|
15
|
+
from ..types.exceptions import ShellRuntimeNotFoundError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class PowerShellScript(ShellScript):
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_shell_script(cls, script: ShellScript):
|
|
22
|
+
data = asdict(script)
|
|
23
|
+
return cls(**{
|
|
24
|
+
field.name: data[field.name]
|
|
25
|
+
for field in fields(ShellScript)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
def to_wrapper_script(self):
|
|
29
|
+
return f"""
|
|
30
|
+
$ErrorActionPreference = "Stop"
|
|
31
|
+
$PSNativeCommandArgumentPassing = "Standard"
|
|
32
|
+
|
|
33
|
+
chcp 65001 | Out-Null
|
|
34
|
+
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
35
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
36
|
+
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
|
37
|
+
|
|
38
|
+
$LASTEXITCODE = $null
|
|
39
|
+
|
|
40
|
+
& {{
|
|
41
|
+
{self.script}
|
|
42
|
+
|
|
43
|
+
$daisSuccess = $?
|
|
44
|
+
$daisExitCode = $LASTEXITCODE
|
|
45
|
+
|
|
46
|
+
if ($daisSuccess) {{ exit 0 }}
|
|
47
|
+
if ($daisExitCode -ne $null) {{ exit $daisExitCode }}
|
|
48
|
+
exit 1
|
|
49
|
+
}}
|
|
50
|
+
""".strip()
|
|
14
51
|
|
|
15
52
|
|
|
16
53
|
@dataclass
|
|
@@ -102,7 +139,13 @@ class PowerShellRuntime(BaseShellRuntime):
|
|
|
102
139
|
"-EncodedCommand", encoded
|
|
103
140
|
]
|
|
104
141
|
|
|
105
|
-
def _prepare_cmd(self, step: CommandStep) -> list[str]:
|
|
142
|
+
def _prepare_cmd(self, step: CommandStep | ShellScript) -> list[str]:
|
|
143
|
+
if isinstance(step, ShellScript):
|
|
144
|
+
script = PowerShellScript.from_shell_script(step)
|
|
145
|
+
return self._make_powershell_commands(
|
|
146
|
+
self._encode(script.to_wrapper_script())
|
|
147
|
+
)
|
|
148
|
+
|
|
106
149
|
env_expander = EnvExpander(step.env or {})
|
|
107
150
|
step.args = env_expander.expand(step.args)
|
|
108
151
|
step = PowerShellCommandStep.from_command_step(step)
|
|
@@ -112,7 +155,7 @@ class PowerShellRuntime(BaseShellRuntime):
|
|
|
112
155
|
|
|
113
156
|
def run_sync(
|
|
114
157
|
self,
|
|
115
|
-
step: CommandStep,
|
|
158
|
+
step: CommandStep | ShellScript,
|
|
116
159
|
on_stdout=None,
|
|
117
160
|
on_stderr=None,
|
|
118
161
|
) -> IOStreamReaderResult:
|
|
@@ -120,7 +163,7 @@ class PowerShellRuntime(BaseShellRuntime):
|
|
|
120
163
|
|
|
121
164
|
async def run(
|
|
122
165
|
self,
|
|
123
|
-
step: CommandStep,
|
|
166
|
+
step: CommandStep | ShellScript,
|
|
124
167
|
on_stdout=None,
|
|
125
168
|
on_stderr=None
|
|
126
169
|
) -> IOStreamReaderResult:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class ShellScript:
|
|
7
|
+
"""Trusted shell source executed directly without command blacklist validation."""
|
|
8
|
+
|
|
9
|
+
script: str
|
|
10
|
+
cwd: str | Path
|
|
11
|
+
env: dict[str, str] | None = None
|
|
12
|
+
timeout: int | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ShellScript",
|
|
17
|
+
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|