memocode 0.2.1__tar.gz → 0.2.2__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.
- {memocode-0.2.1 → memocode-0.2.2}/PKG-INFO +2 -4
- {memocode-0.2.1 → memocode-0.2.2}/README.md +1 -3
- {memocode-0.2.1 → memocode-0.2.2}/memocode.egg-info/PKG-INFO +2 -4
- {memocode-0.2.1 → memocode-0.2.2}/pyproject.toml +1 -1
- {memocode-0.2.1 → memocode-0.2.2}/safety/safety.py +139 -20
- {memocode-0.2.1 → memocode-0.2.2}/control/__init__.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/audit.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/brain.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/__init__.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/cli.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/compressor.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/config.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/context_manager.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/mcp_server.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/memory/__init__.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/memory/consolidation.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/memory/core_memory.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/memory/forgetting.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/memory/recent_memory.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/server.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/chatmem/token_counter.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/fmt.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/llm.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/planner.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/control/project_manager.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/memocode.egg-info/SOURCES.txt +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/memocode.egg-info/dependency_links.txt +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/memocode.egg-info/entry_points.txt +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/memocode.egg-info/requires.txt +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/memocode.egg-info/top_level.txt +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/run.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/safety/__init__.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/safety/backup.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/safety/policy.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/setup.cfg +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/tools/__init__.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/tools/file.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/tools/loader.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/tools/registry.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/tools/shell.py +0 -0
- {memocode-0.2.1 → memocode-0.2.2}/tools/web.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memocode
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Personal AI coding agent with memory, tool execution, and safety controls
|
|
5
5
|
Author: AssassinCHN
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -33,9 +33,7 @@ Personal AI coding agent CLI with memory, tool execution, and safety controls.
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
|
|
37
|
-
cd mcode
|
|
38
|
-
pip install -e .
|
|
36
|
+
pip install memocode
|
|
39
37
|
```
|
|
40
38
|
|
|
41
39
|
Configure your model in `~/.mcode/agent.json` (created on first run):
|
|
@@ -21,9 +21,7 @@ Personal AI coding agent CLI with memory, tool execution, and safety controls.
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
|
|
25
|
-
cd mcode
|
|
26
|
-
pip install -e .
|
|
24
|
+
pip install memocode
|
|
27
25
|
```
|
|
28
26
|
|
|
29
27
|
Configure your model in `~/.mcode/agent.json` (created on first run):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memocode
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Personal AI coding agent with memory, tool execution, and safety controls
|
|
5
5
|
Author: AssassinCHN
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -33,9 +33,7 @@ Personal AI coding agent CLI with memory, tool execution, and safety controls.
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
|
|
37
|
-
cd mcode
|
|
38
|
-
pip install -e .
|
|
36
|
+
pip install memocode
|
|
39
37
|
```
|
|
40
38
|
|
|
41
39
|
Configure your model in `~/.mcode/agent.json` (created on first run):
|
|
@@ -82,7 +82,7 @@ def _extract_paths(command: str, work_dir: str | None = None) -> list[str]:
|
|
|
82
82
|
# relative path (./foo, ../foo) — resolve against work_dir or cwd
|
|
83
83
|
base = work_dir or os.getcwd()
|
|
84
84
|
ep = os.path.normpath(os.path.join(base, p))
|
|
85
|
-
if not ep.startswith(("/proc/", "/sys/")):
|
|
85
|
+
if not ep.startswith(("/proc/", "/sys/")) and ep not in ("/dev/null", "/dev/stdout", "/dev/stderr"):
|
|
86
86
|
result.append(ep)
|
|
87
87
|
return result
|
|
88
88
|
|
|
@@ -266,31 +266,150 @@ def check(task, work_dir: str | None = None,
|
|
|
266
266
|
# Command injection patterns
|
|
267
267
|
_INJECTION_RE = re.compile(r'\$\(|`')
|
|
268
268
|
|
|
269
|
-
#
|
|
270
|
-
|
|
269
|
+
# Leading KEY=value env-var assignments (e.g. PYTHONPATH=... FOO=bar cmd ...)
|
|
270
|
+
_ENV_PREFIX_RE = re.compile(r'^(\w+=\S*\s*)+')
|
|
271
271
|
|
|
272
272
|
DEFAULT_AUTO_WHITELIST: list[str] = [
|
|
273
|
-
#
|
|
274
|
-
"
|
|
275
|
-
|
|
276
|
-
#
|
|
277
|
-
"
|
|
278
|
-
|
|
273
|
+
# ── Navigation ───────────────────────────────────────────────────────────
|
|
274
|
+
"cd", "pwd", "pushd", "popd", "dirs",
|
|
275
|
+
|
|
276
|
+
# ── File inspection ──────────────────────────────────────────────────────
|
|
277
|
+
"ls", "ll", "la", "find", "locate", "which", "type", "file",
|
|
278
|
+
"stat", "du", "df", "realpath", "basename", "dirname", "readlink",
|
|
279
|
+
"lsblk", "lscpu", "lshw", "lsof",
|
|
280
|
+
|
|
281
|
+
# ── File read ────────────────────────────────────────────────────────────
|
|
282
|
+
"cat", "head", "tail", "less", "more", "bat",
|
|
283
|
+
"wc", "od", "xxd", "hexdump", "strings",
|
|
284
|
+
|
|
285
|
+
# ── File create / copy / move ─────────────────────────────────────────────
|
|
286
|
+
"mkdir", "touch", "cp", "mv", "ln", "mktemp", "tee", "split", "install",
|
|
287
|
+
|
|
288
|
+
# ── Archive ──────────────────────────────────────────────────────────────
|
|
289
|
+
"tar", "zip", "unzip", "gzip", "gunzip", "bzip2", "bunzip2",
|
|
290
|
+
"xz", "unxz", "zcat", "7z", "7za",
|
|
291
|
+
|
|
292
|
+
# ── Text processing ──────────────────────────────────────────────────────
|
|
293
|
+
"grep", "rg", "ag", "awk", "sed", "cut", "sort", "uniq",
|
|
294
|
+
"diff", "patch", "tr", "xargs",
|
|
295
|
+
"paste", "join", "expand", "unexpand", "nl", "fold", "column",
|
|
296
|
+
"echo", "printf", "iconv",
|
|
297
|
+
|
|
298
|
+
# ── Encoding / hashing ───────────────────────────────────────────────────
|
|
299
|
+
"base64", "md5sum", "sha1sum", "sha256sum", "sha512sum", "shasum", "cksum",
|
|
300
|
+
"openssl",
|
|
301
|
+
|
|
302
|
+
# ── Search ───────────────────────────────────────────────────────────────
|
|
303
|
+
"fd", "fzf",
|
|
304
|
+
|
|
305
|
+
# ── Environment / system info ─────────────────────────────────────────────
|
|
306
|
+
"env", "printenv", "date", "uname", "hostname", "uptime",
|
|
307
|
+
"whoami", "id", "groups",
|
|
308
|
+
"ps", "pgrep", "pidof", "top", "htop", "free", "vmstat", "iostat",
|
|
309
|
+
"ulimit", "time", "bc",
|
|
310
|
+
|
|
311
|
+
# ── Process control ───────────────────────────────────────────────────────
|
|
312
|
+
"sleep", "wait", "timeout", "watch", "nohup",
|
|
313
|
+
"true", "false", "test", "seq", "kill", "pkill",
|
|
314
|
+
|
|
315
|
+
# ── Network (read / fetch) ─────────────────────────────────────────────────
|
|
316
|
+
"curl", "wget", "http",
|
|
317
|
+
"ping", "traceroute", "nslookup", "dig", "host",
|
|
318
|
+
"netstat", "ss", "ifconfig", "ip",
|
|
319
|
+
"ssh", "scp", "rsync",
|
|
320
|
+
|
|
321
|
+
# ── Permissions ──────────────────────────────────────────────────────────
|
|
322
|
+
"chmod", "chown", "chgrp", "umask",
|
|
323
|
+
|
|
324
|
+
# ── Git ──────────────────────────────────────────────────────────────────
|
|
279
325
|
"git",
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
"pip
|
|
284
|
-
"
|
|
285
|
-
"
|
|
286
|
-
|
|
287
|
-
"
|
|
326
|
+
|
|
327
|
+
# ── Python ───────────────────────────────────────────────────────────────
|
|
328
|
+
"python", "python3", "python3.10", "python3.11", "python3.12", "python3.13",
|
|
329
|
+
"pip", "pip3", "pipenv", "poetry", "uv",
|
|
330
|
+
"pytest", "mypy", "pyright", "ruff", "flake8", "pylint",
|
|
331
|
+
"black", "isort", "autopep8",
|
|
332
|
+
"ipython", "jupyter",
|
|
333
|
+
"pyenv",
|
|
334
|
+
|
|
335
|
+
# ── Node / JS ────────────────────────────────────────────────────────────
|
|
336
|
+
"node", "npm", "npx", "yarn", "pnpm", "bun", "deno",
|
|
337
|
+
"jest", "mocha", "vitest", "eslint", "prettier", "tsc",
|
|
338
|
+
"nvm",
|
|
339
|
+
|
|
340
|
+
# ── Compiled languages ────────────────────────────────────────────────────
|
|
341
|
+
"gcc", "g++", "clang", "clang++", "cc", "c++",
|
|
342
|
+
"make", "cmake", "ninja", "meson", "bear",
|
|
343
|
+
"cargo", "rustc", "rustfmt",
|
|
344
|
+
"go", "gofmt",
|
|
345
|
+
"java", "javac", "jar", "mvn", "gradle",
|
|
346
|
+
"dotnet",
|
|
347
|
+
"swift", "swiftc",
|
|
348
|
+
"ruby", "gem", "bundle", "rspec",
|
|
349
|
+
"perl", "php", "composer",
|
|
350
|
+
"lua", "Rscript",
|
|
351
|
+
|
|
352
|
+
# ── Shell scripting ───────────────────────────────────────────────────────
|
|
353
|
+
"bash", "sh", "zsh", "shellcheck",
|
|
354
|
+
"source",
|
|
355
|
+
|
|
356
|
+
# ── Data / serialisation ──────────────────────────────────────────────────
|
|
357
|
+
"jq", "yq",
|
|
358
|
+
|
|
359
|
+
# ── Containers / orchestration ────────────────────────────────────────────
|
|
360
|
+
"docker", "docker-compose", "docker compose", "podman",
|
|
361
|
+
"kubectl", "helm", "minikube", "kind",
|
|
362
|
+
|
|
363
|
+
# ── Cloud CLIs ────────────────────────────────────────────────────────────
|
|
364
|
+
"aws", "gcloud", "az",
|
|
365
|
+
|
|
366
|
+
# ── Database clients ──────────────────────────────────────────────────────
|
|
367
|
+
"mysql", "mysqldump", "psql", "pg_dump", "sqlite3",
|
|
368
|
+
"redis-cli",
|
|
369
|
+
|
|
370
|
+
# ── Misc ─────────────────────────────────────────────────────────────────
|
|
371
|
+
"man", "tput", "stty", "locale",
|
|
372
|
+
"systemctl", "service",
|
|
288
373
|
]
|
|
289
374
|
|
|
290
375
|
|
|
376
|
+
def _split_shell_ops(command: str) -> list[str]:
|
|
377
|
+
"""Split on && || | ; but NOT inside single- or double-quoted strings."""
|
|
378
|
+
segments: list[str] = []
|
|
379
|
+
current: list[str] = []
|
|
380
|
+
in_single = False
|
|
381
|
+
in_double = False
|
|
382
|
+
i = 0
|
|
383
|
+
while i < len(command):
|
|
384
|
+
c = command[i]
|
|
385
|
+
if c == "'" and not in_double:
|
|
386
|
+
in_single = not in_single
|
|
387
|
+
current.append(c)
|
|
388
|
+
elif c == '"' and not in_single:
|
|
389
|
+
in_double = not in_double
|
|
390
|
+
current.append(c)
|
|
391
|
+
elif not in_single and not in_double:
|
|
392
|
+
two = command[i:i + 2]
|
|
393
|
+
if two in ("&&", "||"):
|
|
394
|
+
segments.append("".join(current))
|
|
395
|
+
current = []
|
|
396
|
+
i += 2
|
|
397
|
+
continue
|
|
398
|
+
elif c in ("|", ";"):
|
|
399
|
+
segments.append("".join(current))
|
|
400
|
+
current = []
|
|
401
|
+
else:
|
|
402
|
+
current.append(c)
|
|
403
|
+
else:
|
|
404
|
+
current.append(c)
|
|
405
|
+
i += 1
|
|
406
|
+
segments.append("".join(current))
|
|
407
|
+
return segments
|
|
408
|
+
|
|
409
|
+
|
|
291
410
|
def _matches_whitelist(segment: str, whitelist: list[str]) -> bool:
|
|
292
|
-
"""Return True if the command segment starts with a whitelist entry
|
|
293
|
-
seg = segment.lower().strip()
|
|
411
|
+
"""Return True if the command segment (after stripping env-var prefixes) starts with a whitelist entry."""
|
|
412
|
+
seg = _ENV_PREFIX_RE.sub("", segment).lower().strip()
|
|
294
413
|
for entry in whitelist:
|
|
295
414
|
e = entry.lower().strip()
|
|
296
415
|
if seg == e or seg.startswith(e + " "):
|
|
@@ -352,7 +471,7 @@ def check_auto(task, work_dir: str | None = None,
|
|
|
352
471
|
reason="Auto mode: command injection pattern blocked")
|
|
353
472
|
|
|
354
473
|
# Whitelist check — every pipe/chain segment must be in whitelist
|
|
355
|
-
for seg in
|
|
474
|
+
for seg in _split_shell_ops(command):
|
|
356
475
|
seg = seg.strip()
|
|
357
476
|
if not seg:
|
|
358
477
|
continue
|
|
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
|
|
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
|
|
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
|
|
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
|