rockycode 0.1.0__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.
- rockycode/__init__.py +1 -0
- rockycode/banner.py +37 -0
- rockycode/cli.py +1386 -0
- rockycode/config.py +178 -0
- rockycode/dream/__init__.py +9 -0
- rockycode/dream/core.py +523 -0
- rockycode/dream/judge.py +134 -0
- rockycode/dream/mining.py +152 -0
- rockycode/dream/proposals.py +440 -0
- rockycode/engine/__init__.py +10 -0
- rockycode/engine/artifact.py +367 -0
- rockycode/engine/budget.py +90 -0
- rockycode/engine/checks.py +157 -0
- rockycode/engine/compaction.py +181 -0
- rockycode/engine/container.py +225 -0
- rockycode/engine/effort.py +46 -0
- rockycode/engine/events.py +101 -0
- rockycode/engine/explore.py +592 -0
- rockycode/engine/goal.py +541 -0
- rockycode/engine/goal_review.py +161 -0
- rockycode/engine/goal_session.py +259 -0
- rockycode/engine/headless.py +481 -0
- rockycode/engine/loop.py +711 -0
- rockycode/engine/lsp.py +473 -0
- rockycode/engine/mcp.py +364 -0
- rockycode/engine/modes.py +123 -0
- rockycode/engine/outcome.py +81 -0
- rockycode/engine/permission.py +198 -0
- rockycode/engine/planmode.py +249 -0
- rockycode/engine/providers.py +196 -0
- rockycode/engine/redact.py +83 -0
- rockycode/engine/safety.py +139 -0
- rockycode/engine/sandbox.py +219 -0
- rockycode/engine/server.py +431 -0
- rockycode/engine/skills.py +178 -0
- rockycode/engine/titler.py +46 -0
- rockycode/engine/tools.py +479 -0
- rockycode/engine/trajectory.py +131 -0
- rockycode/engine/web.py +431 -0
- rockycode/engine/worktree.py +128 -0
- rockycode/memory/__init__.py +7 -0
- rockycode/memory/index.py +260 -0
- rockycode/memory/store.py +331 -0
- rockycode/modes/learn/learn.md +46 -0
- rockycode/modes/research/deep-research.md +53 -0
- rockycode/modes/research/paper-reading.md +49 -0
- rockycode/modes/research/prove.md +60 -0
- rockycode/modes/research/whiteboard.md +64 -0
- rockycode/onboarding.py +332 -0
- rockycode/palette.py +15 -0
- rockycode/pricing.py +178 -0
- rockycode/prompts/__init__.py +0 -0
- rockycode/prompts/rocky.py +257 -0
- rockycode/routines.py +287 -0
- rockycode/runners/__init__.py +0 -0
- rockycode/runners/agent.py +273 -0
- rockycode/runners/data.py +61 -0
- rockycode/runners/raw.py +176 -0
- rockycode/score.py +114 -0
- rockycode/session.py +298 -0
- rockycode/skills/architecture-viz/SKILL.md +71 -0
- rockycode/skills/architecture-viz/template.html +87 -0
- rockycode/skills/lean-prover/SKILL.md +155 -0
- rockycode/skills/lean-prover/torchlean-api.md +85 -0
- rockycode/tui/__init__.py +1 -0
- rockycode/tui/app.py +2450 -0
- rockycode/tui/exitsheet.py +181 -0
- rockycode/tui/goal_screen.py +315 -0
- rockycode/tui/mdterm.py +232 -0
- rockycode/tui/mdview.py +99 -0
- rockycode/tui/modepicker.py +103 -0
- rockycode/tui/permission.py +154 -0
- rockycode/tui/plangate.py +110 -0
- rockycode/tui/prompt_history.py +77 -0
- rockycode/tui/proposalcard.py +126 -0
- rockycode/tui/resume.py +142 -0
- rockycode/tui/rocky_pet.py +96 -0
- rockycode/tui/routinecard.py +123 -0
- rockycode-0.1.0.dist-info/METADATA +488 -0
- rockycode-0.1.0.dist-info/RECORD +83 -0
- rockycode-0.1.0.dist-info/WHEEL +4 -0
- rockycode-0.1.0.dist-info/entry_points.txt +2 -0
- rockycode-0.1.0.dist-info/licenses/LICENSE +21 -0
rockycode/config.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""User config — persistent preferences (currency, theme, language, …).
|
|
2
|
+
|
|
3
|
+
Resolution order (later wins): built-in DEFAULTS → global
|
|
4
|
+
`~/.rockycode/config.toml` → project `<wd>/.rockycode/config.toml`. CLI flags
|
|
5
|
+
and env vars still override at runtime; this file is just for sticky
|
|
6
|
+
preferences you don't want to retype.
|
|
7
|
+
|
|
8
|
+
TOML for reading (stdlib tomllib) to match the ecosystem; writes are a flat
|
|
9
|
+
hand-rolled emit (the config is flat, so no toml-writer dependency needed).
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import tomllib
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, Optional
|
|
16
|
+
|
|
17
|
+
GLOBAL_PATH = Path.home() / ".rockycode" / "config.toml"
|
|
18
|
+
PROJECT_REL = Path(".rockycode") / "config.toml"
|
|
19
|
+
|
|
20
|
+
DEFAULTS: dict[str, Any] = {
|
|
21
|
+
"currency": "usd", # usd | cny — which official price table to show cost in
|
|
22
|
+
"theme": "dark", # dark | light
|
|
23
|
+
# Reply language: auto mirrors whatever language the user writes in; zh
|
|
24
|
+
# adds a native 语言要求 block to the prompt (reasoning + replies in
|
|
25
|
+
# Chinese, code/identifiers untouched). Resolved once at session build.
|
|
26
|
+
# UI strings are en for now; zh planned on this same key.
|
|
27
|
+
"language": "auto", # auto | en | zh
|
|
28
|
+
"permission": "ask", # yolo | ask | careful — tool-approval strictness
|
|
29
|
+
# self-evolve is EXPERIMENTAL and ships default-OFF: nothing fires unless the
|
|
30
|
+
# user opts in (set exit_sheet=auto|on and dream=auto). auto = only when the
|
|
31
|
+
# dream pipeline is alive (memory on + Ollama reachable), so opting in still
|
|
32
|
+
# never nags a user without the local stack.
|
|
33
|
+
"exit_sheet": "off", # off | auto | on — the exit feedback sheet (auto-skips after 60s)
|
|
34
|
+
"dream": "manual", # manual | auto — catch-up dream pass at launch (local Ollama)
|
|
35
|
+
# Collaboration mode applied at launch ("" = none). Set by `/research always`.
|
|
36
|
+
# Resolved against BUILT-IN modes only — a cloned repo's project config must
|
|
37
|
+
# not auto-inject a project-local mode file into the prompt (trust rule,
|
|
38
|
+
# same spirit as permission never loosening).
|
|
39
|
+
"mode": "",
|
|
40
|
+
# Model limits — set these for a non-DeepSeek model (env ROCKYCODE_CONTEXT_WINDOW
|
|
41
|
+
# / ROCKYCODE_MAX_TOKENS and the CLI flags override at runtime).
|
|
42
|
+
"context_window": 1_048_576, # DeepSeek V4 = 1M; compaction acts at 50%
|
|
43
|
+
"max_tokens": 384_000, # per-call output cap incl. CoT (DeepSeek V4 max = 384K)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_ALLOWED = {
|
|
47
|
+
"currency": {"usd", "cny"},
|
|
48
|
+
"theme": {"dark", "light"},
|
|
49
|
+
"language": {"auto", "en", "zh"},
|
|
50
|
+
"permission": {"yolo", "ask", "careful"},
|
|
51
|
+
"exit_sheet": {"auto", "on", "off"},
|
|
52
|
+
"dream": {"auto", "manual"},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _read(path: Path) -> dict:
|
|
57
|
+
if not path.exists():
|
|
58
|
+
return {}
|
|
59
|
+
try:
|
|
60
|
+
return tomllib.loads(path.read_text())
|
|
61
|
+
except (tomllib.TOMLDecodeError, OSError):
|
|
62
|
+
return {}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# Tool-permission strictness, ranked. A project file may TIGHTEN the guard but
|
|
66
|
+
# never LOOSEN it (see load()).
|
|
67
|
+
_PERM_RANK = {"careful": 2, "ask": 1, "yolo": 0}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _sanitize(raw: dict, base: dict) -> dict:
|
|
71
|
+
"""Merge *raw* onto *base*, dropping anything malformed.
|
|
72
|
+
|
|
73
|
+
Config can come from an untrusted cloned repo, so a bad value must never
|
|
74
|
+
crash the app or silently mean something dangerous. Unknown keys are
|
|
75
|
+
ignored; numeric fields are coerced (a quoted TOML "7.2" arrives as str);
|
|
76
|
+
enum fields must be in _ALLOWED or the base value is kept.
|
|
77
|
+
"""
|
|
78
|
+
out = dict(base)
|
|
79
|
+
for k, v in raw.items():
|
|
80
|
+
if k not in DEFAULTS:
|
|
81
|
+
continue
|
|
82
|
+
default = DEFAULTS[k]
|
|
83
|
+
if isinstance(default, (int, float)) and not isinstance(default, bool):
|
|
84
|
+
try:
|
|
85
|
+
v = int(v) if isinstance(default, int) else float(v)
|
|
86
|
+
except (TypeError, ValueError):
|
|
87
|
+
continue
|
|
88
|
+
if v <= 0: # window / output must be positive
|
|
89
|
+
continue
|
|
90
|
+
if k in _ALLOWED and v not in _ALLOWED[k]:
|
|
91
|
+
continue
|
|
92
|
+
out[k] = v
|
|
93
|
+
return out
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def load(workdir: Optional[Path] = None) -> dict:
|
|
97
|
+
cfg = _sanitize(_read(GLOBAL_PATH), DEFAULTS)
|
|
98
|
+
if workdir is not None:
|
|
99
|
+
proj = _sanitize(_read(workdir / PROJECT_REL), cfg)
|
|
100
|
+
# Security: a project config (possibly from a cloned repo) may make the
|
|
101
|
+
# tool-approval guard STRICTER but never weaker. Clamp any downgrade —
|
|
102
|
+
# otherwise a hostile repo ships permission="yolo" and runs every tool
|
|
103
|
+
# call unprompted. Tightening (ask→careful) is honored.
|
|
104
|
+
if _PERM_RANK.get(proj.get("permission"), 1) < _PERM_RANK.get(cfg["permission"], 1):
|
|
105
|
+
proj["permission"] = cfg["permission"]
|
|
106
|
+
cfg = proj
|
|
107
|
+
return cfg
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _coerce(key: str, raw: str) -> Any:
|
|
111
|
+
default = DEFAULTS.get(key)
|
|
112
|
+
if isinstance(default, bool):
|
|
113
|
+
return raw.strip().lower() in {"1", "true", "yes", "on"}
|
|
114
|
+
if isinstance(default, (int, float)) and not isinstance(default, bool):
|
|
115
|
+
try:
|
|
116
|
+
v = int(raw) if isinstance(default, int) else float(raw)
|
|
117
|
+
except ValueError:
|
|
118
|
+
return default
|
|
119
|
+
return v if v > 0 else default
|
|
120
|
+
return raw.strip()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _emit(cfg: dict) -> str:
|
|
124
|
+
lines = []
|
|
125
|
+
for k, v in cfg.items():
|
|
126
|
+
if isinstance(v, bool):
|
|
127
|
+
lines.append(f"{k} = {'true' if v else 'false'}")
|
|
128
|
+
elif isinstance(v, (int, float)):
|
|
129
|
+
lines.append(f"{k} = {v}")
|
|
130
|
+
else:
|
|
131
|
+
lines.append(f'{k} = "{v}"')
|
|
132
|
+
return "\n".join(lines) + "\n"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def set_value(key: str, raw: str) -> tuple[Any, Optional[str]]:
|
|
136
|
+
"""Persist key=value to the GLOBAL config. Returns (value, error)."""
|
|
137
|
+
if key not in DEFAULTS:
|
|
138
|
+
return None, f"unknown key '{key}'. known: {', '.join(sorted(DEFAULTS))}"
|
|
139
|
+
default = DEFAULTS[key]
|
|
140
|
+
if isinstance(default, int) and not isinstance(default, bool):
|
|
141
|
+
try:
|
|
142
|
+
value = int(raw)
|
|
143
|
+
except ValueError:
|
|
144
|
+
return None, f"{key} must be a positive integer (got {raw!r})"
|
|
145
|
+
if value <= 0:
|
|
146
|
+
return None, f"{key} must be positive (got {value})"
|
|
147
|
+
GLOBAL_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
148
|
+
current = _read(GLOBAL_PATH)
|
|
149
|
+
current[key] = value
|
|
150
|
+
GLOBAL_PATH.write_text(_emit(current))
|
|
151
|
+
return value, None
|
|
152
|
+
value = _coerce(key, raw)
|
|
153
|
+
if key in _ALLOWED and value not in _ALLOWED[key]:
|
|
154
|
+
return None, f"invalid value for {key}: {value!r}. allowed: {', '.join(sorted(_ALLOWED[key]))}"
|
|
155
|
+
GLOBAL_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
156
|
+
current = _read(GLOBAL_PATH)
|
|
157
|
+
current[key] = value
|
|
158
|
+
GLOBAL_PATH.write_text(_emit(current))
|
|
159
|
+
return value, None
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def set_project_value(workdir: Path, key: str, raw: str) -> tuple[Any, Optional[str]]:
|
|
163
|
+
"""Persist key=value to THIS folder's .rockycode/config.toml — folder-scoped
|
|
164
|
+
defaults like `/research always`. Same validation as set_value."""
|
|
165
|
+
if key not in DEFAULTS:
|
|
166
|
+
return None, f"unknown key '{key}'. known: {', '.join(sorted(DEFAULTS))}"
|
|
167
|
+
value = _coerce(key, raw)
|
|
168
|
+
if key in _ALLOWED and value not in _ALLOWED[key]:
|
|
169
|
+
return None, f"invalid value for {key}: {value!r}. allowed: {', '.join(sorted(_ALLOWED[key]))}"
|
|
170
|
+
path = Path(workdir) / PROJECT_REL
|
|
171
|
+
try:
|
|
172
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
173
|
+
current = _read(path)
|
|
174
|
+
current[key] = value
|
|
175
|
+
path.write_text(_emit(current))
|
|
176
|
+
except OSError as e:
|
|
177
|
+
return None, f"could not write {path}: {e}"
|
|
178
|
+
return value, None
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""rockycode dream: idle-time memory consolidation on a local Ollama model.
|
|
2
|
+
|
|
3
|
+
M2 of docs/memory-dream.md — episode digestion, reconciliation, project
|
|
4
|
+
state, re-embedding. No daemon: manual `rockycode dream` now, TUI idle
|
|
5
|
+
trigger in M3.
|
|
6
|
+
"""
|
|
7
|
+
from rockycode.dream.core import DreamReport, DreamRunner, OllamaChat
|
|
8
|
+
|
|
9
|
+
__all__ = ["DreamReport", "DreamRunner", "OllamaChat"]
|