Merge remote-tracking branch 'shareai/main' into fix/pr-536-readline-prompt-wrap

# Conflicts:
#	web/src/data/generated/versions.json
This commit is contained in:
Haoran
2026-08-25 21:38:38 +08:00
95 changed files with 1673 additions and 922 deletions

View File

@@ -74,7 +74,7 @@ def run_bash(command: str) -> str:
def run_read(path: str, limit: int | None = None) -> str:
try:
file_path = (WORKDIR / path).resolve()
lines = file_path.read_text().splitlines()
lines = file_path.read_text(encoding="utf-8").splitlines()
if limit and limit < len(lines):
lines = lines[:limit] + [f"... ({len(lines) - limit} more lines)"]
return "\n".join(lines)
@@ -86,7 +86,7 @@ def run_write(path: str, content: str) -> str:
try:
file_path = (WORKDIR / path).resolve()
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)
file_path.write_text(content, encoding="utf-8")
return f"Wrote {len(content)} bytes to {path}"
except Exception as error:
return f"Error: {error}"
@@ -95,10 +95,10 @@ def run_write(path: str, content: str) -> str:
def run_edit(path: str, old_text: str, new_text: str) -> str:
try:
file_path = (WORKDIR / path).resolve()
text = file_path.read_text()
text = file_path.read_text(encoding="utf-8")
if old_text not in text:
return f"Error: text not found in {path}"
file_path.write_text(text.replace(old_text, new_text, 1))
file_path.write_text(text.replace(old_text, new_text, 1), encoding="utf-8")
return f"Edited {path}"
except Exception as error:
return f"Error: {error}"
@@ -106,12 +106,15 @@ def run_edit(path: str, old_text: str, new_text: str) -> str:
def run_glob(pattern: str) -> str:
try:
matches = [
matches = sorted({
match
for match in glob.glob(pattern, root_dir=WORKDIR)
for match in glob.glob(pattern, root_dir=WORKDIR, recursive=True)
if (WORKDIR / match).resolve().is_relative_to(WORKDIR)
]
return "\n".join(matches) if matches else "(no matches)"
})
shown = matches[:200]
if len(matches) > 200:
shown.append("... (more matches omitted; narrow the pattern)")
return "\n".join(shown) if shown else "(no matches)"
except Exception as error:
return f"Error: {error}"
@@ -137,7 +140,7 @@ TOOLS = [
"old_text": {"type": "string"},
"new_text": {"type": "string"}},
"required": ["path", "old_text", "new_text"]}},
{"name": "glob", "description": "Find files matching a glob pattern.",
{"name": "glob", "description": "Find files matching a glob pattern; ** matches recursively.",
"input_schema": {"type": "object",
"properties": {"pattern": {"type": "string"}},
"required": ["pattern"]}},
@@ -363,7 +366,7 @@ def save_durable_jobs():
f"{DURABLE_PATH.name}.{os.getpid()}.{threading.get_ident()}.tmp"
)
try:
temporary.write_text(json.dumps(payload, indent=2))
temporary.write_text(json.dumps(payload, indent=2), encoding="utf-8")
os.replace(temporary, DURABLE_PATH)
finally:
temporary.unlink(missing_ok=True)
@@ -373,7 +376,7 @@ def load_durable_jobs():
if not DURABLE_PATH.exists():
return
try:
payload = json.loads(DURABLE_PATH.read_text())
payload = json.loads(DURABLE_PATH.read_text(encoding="utf-8"))
if not isinstance(payload, list):
raise ValueError("expected a JSON list")
except (OSError, json.JSONDecodeError, ValueError) as error: