dsh-open-dream-rsi 0.2.0 → 0.2.1
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.
- package/README.md +2 -2
- package/open_dream_rsi/__init__.py +1 -1
- package/open_dream_rsi/core/policygen.py +8 -0
- package/open_dream_rsi/sandbox.py +39 -12
- package/open_dream_rsi/tools.py +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,8 +40,8 @@ directory holding your `tasks.json`:
|
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
42
|
# from the npm registry, a tarball, a checkout, or straight from GitHub — pick one:
|
|
43
|
-
dsh plugin --profile <name> add dsh-open-dream-rsi # or pin: dsh-open-dream-rsi@0.2.
|
|
44
|
-
dsh plugin --profile <name> add /path/to/dsh-open-dream-rsi-0.2.
|
|
43
|
+
dsh plugin --profile <name> add dsh-open-dream-rsi # or pin: dsh-open-dream-rsi@0.2.1
|
|
44
|
+
dsh plugin --profile <name> add /path/to/dsh-open-dream-rsi-0.2.1.tgz
|
|
45
45
|
dsh plugin --profile <name> add /path/to/open-dream-rsi/plugins/deepseek_harness
|
|
46
46
|
dsh plugin --profile <name> add github:patrykorwat/open-dream-rsi#path:plugins/deepseek_harness
|
|
47
47
|
|
|
@@ -302,6 +302,10 @@ class PolicySandbox:
|
|
|
302
302
|
)
|
|
303
303
|
except subprocess.TimeoutExpired:
|
|
304
304
|
return PolicyRun(None, "policy execution timed out")
|
|
305
|
+
except subprocess.SubprocessError as exc:
|
|
306
|
+
# A failed spawn (e.g. "Exception occurred in preexec_fn" under a
|
|
307
|
+
# low hard rlimit) must not kill the whole cycle.
|
|
308
|
+
return PolicyRun(None, f"sandbox spawn failed: {exc}")
|
|
305
309
|
finally:
|
|
306
310
|
for p in (src_path, fr_path, harness_path):
|
|
307
311
|
p.unlink(missing_ok=True)
|
|
@@ -339,6 +343,10 @@ class PolicySandbox:
|
|
|
339
343
|
)
|
|
340
344
|
except subprocess.TimeoutExpired:
|
|
341
345
|
return None, [], 0, "policy rollout timed out"
|
|
346
|
+
except subprocess.SubprocessError as exc:
|
|
347
|
+
# See choose(): a failed spawn is an errored rollout, not a
|
|
348
|
+
# crashed cycle.
|
|
349
|
+
return None, [], 0, f"sandbox spawn failed: {exc}"
|
|
342
350
|
finally:
|
|
343
351
|
for p in (src_path, world_path, harness_path):
|
|
344
352
|
p.unlink(missing_ok=True)
|
|
@@ -57,21 +57,51 @@ def _memory_mb() -> int:
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def _make_preexec(timeout: float):
|
|
60
|
-
"""preexec_fn: RLIMIT_AS / RLIMIT_CPU / RLIMIT_NPROC for the child.
|
|
60
|
+
"""preexec_fn: RLIMIT_AS / RLIMIT_CPU / RLIMIT_NPROC for the child.
|
|
61
|
+
|
|
62
|
+
Best-effort by design: in restrictive environments (a hard rlimit below
|
|
63
|
+
the request — common for daemons and desktop sandboxes) ``setrlimit``
|
|
64
|
+
would raise and kill the spawn with ``Exception occurred in
|
|
65
|
+
preexec_fn``, so each limit is clamped to the hard ceiling and applied
|
|
66
|
+
only when it can be.
|
|
67
|
+
"""
|
|
61
68
|
import resource
|
|
62
69
|
|
|
63
70
|
mem_bytes = _memory_mb() * 1024 * 1024
|
|
64
71
|
cpu_soft = max(2, int(timeout) + 1)
|
|
65
72
|
|
|
73
|
+
def _apply(limit: int, soft: int, hard_extra: Optional[int]) -> bool:
|
|
74
|
+
"""Set one rlimit, clamped to the environment's hard ceiling."""
|
|
75
|
+
try:
|
|
76
|
+
_, hard = resource.getrlimit(limit)
|
|
77
|
+
except (ValueError, OSError):
|
|
78
|
+
hard = resource.RLIM_INFINITY
|
|
79
|
+
if hard == 0:
|
|
80
|
+
# The environment forbids this resource entirely; applying
|
|
81
|
+
# soft=0 would insta-kill the child, so skip it.
|
|
82
|
+
return False
|
|
83
|
+
if hard != resource.RLIM_INFINITY:
|
|
84
|
+
soft = min(soft, hard)
|
|
85
|
+
if hard_extra is not None:
|
|
86
|
+
hard = (soft + hard_extra) if hard == resource.RLIM_INFINITY \
|
|
87
|
+
else min(hard, soft + hard_extra)
|
|
88
|
+
try:
|
|
89
|
+
resource.setrlimit(limit, (soft, hard))
|
|
90
|
+
except (ValueError, OSError):
|
|
91
|
+
return False
|
|
92
|
+
return True
|
|
93
|
+
|
|
66
94
|
def _limits() -> None: # runs in the forked child only
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
# Each limit is best-effort: degrade to fewer enforced limits
|
|
96
|
+
# rather than kill the spawn.
|
|
97
|
+
_apply(resource.RLIMIT_AS, mem_bytes, None)
|
|
98
|
+
_apply(resource.RLIMIT_CPU, cpu_soft, 1)
|
|
99
|
+
# RLIMIT_NPROC counts THREADS of this uid (shared with the parent),
|
|
100
|
+
# so the floor must sit ABOVE the uid's current task count or every
|
|
101
|
+
# fork fails with EAGAIN. Count threads via /proc, fall back to the
|
|
102
|
+
# static floor where /proc is absent.
|
|
103
|
+
existing = 0
|
|
69
104
|
try:
|
|
70
|
-
# RLIMIT_NPROC counts THREADS of this uid (shared with the
|
|
71
|
-
# parent), so the floor must sit ABOVE the uid's current task
|
|
72
|
-
# count or every fork fails with EAGAIN. Count threads via
|
|
73
|
-
# /proc, fall back to the static floor where /proc is absent.
|
|
74
|
-
existing = 0
|
|
75
105
|
for entry in os.listdir("/proc"):
|
|
76
106
|
if not entry.isdigit():
|
|
77
107
|
continue
|
|
@@ -87,10 +117,7 @@ def _make_preexec(timeout: float):
|
|
|
87
117
|
except OSError:
|
|
88
118
|
existing = 0
|
|
89
119
|
cap = max(MAX_PROCS, existing + 64)
|
|
90
|
-
|
|
91
|
-
resource.setrlimit(resource.RLIMIT_NPROC, (cap, cap))
|
|
92
|
-
except (ValueError, OSError):
|
|
93
|
-
pass # platform without NPROC limits
|
|
120
|
+
_apply(resource.RLIMIT_NPROC, cap, None)
|
|
94
121
|
|
|
95
122
|
return _limits
|
|
96
123
|
|
package/open_dream_rsi/tools.py
CHANGED
|
@@ -101,6 +101,12 @@ class CodeVerifier:
|
|
|
101
101
|
except subprocess.TimeoutExpired:
|
|
102
102
|
return {"ok": False, "error": "execution timed out",
|
|
103
103
|
"defined": [], "stdout": ""}
|
|
104
|
+
except subprocess.SubprocessError as exc:
|
|
105
|
+
# Restrictive environments can fail the spawn itself (e.g.
|
|
106
|
+
# "Exception occurred in preexec_fn" under a low hard rlimit):
|
|
107
|
+
# report sandbox evidence instead of killing the whole cycle.
|
|
108
|
+
return {"ok": False, "error": f"sandbox spawn failed: {exc}",
|
|
109
|
+
"defined": [], "stdout": ""}
|
|
104
110
|
finally:
|
|
105
111
|
Path(path).unlink(missing_ok=True)
|
|
106
112
|
line = proc.stdout.strip().splitlines()[-1] if proc.stdout.strip() else ""
|
|
@@ -129,6 +135,10 @@ class CodeVerifier:
|
|
|
129
135
|
)
|
|
130
136
|
except subprocess.TimeoutExpired:
|
|
131
137
|
return ToolResult(False, 0.0, "execution timed out")
|
|
138
|
+
except subprocess.SubprocessError as exc:
|
|
139
|
+
# See smoke_run: a failed spawn is sandbox evidence, not a
|
|
140
|
+
# crashed cycle.
|
|
141
|
+
return ToolResult(False, 0.0, f"sandbox spawn failed: {exc}")
|
|
132
142
|
finally:
|
|
133
143
|
Path(path).unlink(missing_ok=True)
|
|
134
144
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-open-dream-rsi",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Let your coding agent dream: strategies must survive counterfactual replay before they earn trust. An offline self-improvement loop over an evolving world model — no fine-tuning, the LLM stays frozen. Speaks MCP. Ships its Python server inside the package — the only requirement is a system python3 (3.10+) on PATH — and the plugin's bridge serves the dreamer's LLM calls from the model your harness is already configured with (no API keys, no env, no extra endpoints).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|