Files
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

348 lines
12 KiB
Python

# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from mirage.commands.builtin.find_eval import FindEntry, keep
from mirage.commands.builtin.find_parse import parse_find_expression
from mirage.commands.errors import FindParseError
from mirage.commands.safeguard import resolve_across_mounts
from mirage.io import IOResult
from mirage.io.stream import materialize
from mirage.io.types import ByteSource
from mirage.types import PathSpec
from mirage.workspace.executor.find_action_dispatch import _apply_find_actions
from mirage.workspace.mount import MountRegistry
from mirage.workspace.types import ExecutionNode
_TRAVERSAL_CMDS = frozenset({"find", "tree", "du"})
def _path_segments(path: str) -> list[str]:
return [s for s in path.strip("/").split("/") if s]
def _should_fan_out(
cmd_name: str,
paths: list[PathSpec],
flag_kwargs: dict,
registry: MountRegistry,
) -> bool:
"""Whether `cmd` on this path should run across multiple mounts.
True when the command is in the traversal whitelist (find/tree/du)
and the path has at least one descendant mount; or for grep with
-r/-R; or for ls -R. Returns False when there's no descendant
mount under the path (single-mount dispatch is correct).
"""
if not paths:
return False
target = paths[0].virtual
if not registry.descendant_mounts(target):
return False
if cmd_name in _TRAVERSAL_CMDS:
return True
if cmd_name == "grep":
return (flag_kwargs.get("r") is True or flag_kwargs.get("R") is True
or flag_kwargs.get("recursive") is True)
if cmd_name == "ls":
return flag_kwargs.get("R") is True
return False
def _adjust_depth_flags(
flag_kwargs: dict,
parent_path: str,
mount_prefix: str,
) -> dict | None:
"""Adjust find's -maxdepth/-mindepth for a fan-out into a child mount.
Returns the new kwargs dict, or None if the child mount falls
outside the depth budget (caller should skip it).
"""
parent_depth = len(_path_segments(parent_path))
mount_depth = len(_path_segments(mount_prefix))
delta = mount_depth - parent_depth
new = dict(flag_kwargs)
if "maxdepth" in new:
raw_md = new["maxdepth"]
if isinstance(raw_md, list):
raw_md = raw_md[0] if raw_md else None
try:
md = int(raw_md) - delta
except (TypeError, ValueError):
md = None
if md is not None:
if md < 0:
return None
new["maxdepth"] = str(md)
if "mindepth" in new:
raw_mn = new["mindepth"]
if isinstance(raw_mn, list):
raw_mn = raw_mn[0] if raw_mn else None
try:
mn = max(0, int(raw_mn) - delta)
new["mindepth"] = str(mn)
except (TypeError, ValueError):
pass
return new
def _adjust_depth_texts(
texts: list[str],
parent_path: str,
mount_prefix: str,
) -> list[str]:
"""Adjust -maxdepth/-mindepth values inside a find expression.
The generic find parses depth from the expression tokens (`texts`),
not from flag kwargs, so a fan-out into a deeper child mount must
rewrite the depth values by the parent-to-mount delta. Mirrors
`_adjust_depth_flags`.
Args:
texts (list[str]): the find expression tokens.
parent_path (str): the find start path the fan-out runs from.
mount_prefix (str): the child mount prefix being descended into.
"""
delta = len(_path_segments(mount_prefix)) - len(
_path_segments(parent_path))
if delta == 0:
return list(texts)
out = list(texts)
i = 0
while i < len(out) - 1:
tok = out[i]
if tok in ("-maxdepth", "-mindepth"):
try:
val = int(out[i + 1])
except ValueError:
i += 2
continue
if tok == "-maxdepth":
out[i + 1] = str(val - delta)
else:
out[i + 1] = str(max(0, val - delta))
i += 2
continue
i += 1
return out
def _synthesize_find_mount_entries(
target_path: str,
descendants: list,
texts: list[str],
) -> str:
"""Return synthetic find lines for descendant mount roots.
`find /` and friends should list mount prefixes as directory
entries even though no per-mount find emits its own root. The find
expression is parsed into a predicate tree and evaluated per mount
root (kind "d"), mirroring the per-backend cores, so -not / -o /
-path / -type and the -maxdepth / -mindepth window all apply.
Args:
target_path (str): the find start path the fan-out runs from.
descendants (list): descendant mounts to inject as entries.
texts (list[str]): the find expression tokens.
"""
try:
expr = parse_find_expression(list(texts))
except FindParseError:
return ""
tree = expr.tree
max_depth = expr.maxdepth
min_depth = expr.mindepth if expr.mindepth is not None else 0
parent_depth = len(_path_segments(target_path))
out: list[str] = []
for m in descendants:
prefix_no_slash = m.prefix.rstrip("/")
depth = len(_path_segments(prefix_no_slash)) - parent_depth
if max_depth is not None and depth > max_depth:
continue
base = prefix_no_slash.rsplit("/", 1)[-1] or prefix_no_slash
entry = FindEntry(key=prefix_no_slash,
name=base,
kind="d",
depth=depth)
if not keep(entry, tree, min_depth):
continue
out.append(prefix_no_slash)
return "\n".join(out)
async def _filter_under_prefixes(
stdout: ByteSource,
descendant_prefixes: list[str],
) -> bytes:
"""Drop lines whose path falls under any descendant mount prefix.
Path is taken from the start of the line up to the first tab,
colon, or whitespace (handles find / du / grep output formats).
Lines that do not start with `/` are passed through.
"""
data = await materialize(stdout)
text = data.decode("utf-8", errors="replace")
out_lines: list[str] = []
for line in text.split("\n"):
if line == "":
continue
path = line
for sep in ("\t", ":"):
if sep in path:
path = path.split(sep, 1)[0]
break
if path.startswith("/"):
shadowed = False
for pre in descendant_prefixes:
if path == pre or path.startswith(pre + "/"):
shadowed = True
break
if shadowed:
continue
out_lines.append(line)
return ("\n".join(out_lines) + "\n").encode("utf-8") if out_lines else b""
async def _drop_mount_root_line(stdout: ByteSource, mount_root: str) -> bytes:
"""Drop a descendant find's own mount-root line.
A per-mount find now emits its start directory, so a descendant
mount's find yields its mount-root path. The mount-point entry is
instead synthesized centrally (with the mount's display name and the
full predicate tree applied), so the raw root line is dropped here to
avoid a duplicate that skips the name filter.
Args:
stdout (ByteSource): descendant find output.
mount_root (str): the descendant mount root path.
"""
data = await materialize(stdout)
text = data.decode("utf-8", errors="replace")
out_lines = [
line for line in text.split("\n") if line != "" and line != mount_root
]
return ("\n".join(out_lines) + "\n").encode("utf-8") if out_lines else b""
async def _fan_out_traversal(
cmd_name: str,
paths: list[PathSpec],
texts: list[str],
flag_kwargs: dict,
registry: MountRegistry,
primary_mount: object,
cwd: str,
cmd_str: str,
stdin: ByteSource | None,
) -> tuple[ByteSource | None, IOResult, ExecutionNode]:
"""Run a traversal command across the parent mount + descendant mounts.
Each mount runs the command with its own root as the path argument
(depth flags adjusted for find/tree). Outputs are concatenated in
mount-prefix-sorted order. The parent mount's output is filtered to
drop lines that fall under any descendant mount (avoids duplicates
when the parent's resource has shadowed keys).
For `find`, mount-prefix paths themselves are injected as synthetic
directory entries (subject to depth and -type filters) because
mirage's per-mount find doesn't emit the path argument itself.
"""
target_path = paths[0].virtual
descendants = registry.descendant_mounts(target_path)
descendant_prefixes = [m.prefix.rstrip("/") for m in descendants]
all_stdout: list[bytes] = []
merged_io = IOResult()
final_exit = 0
success_seen = False
for mount in [primary_mount] + list(descendants):
if mount is primary_mount:
sub_paths = list(paths)
sub_flags = dict(flag_kwargs)
sub_texts = list(texts)
else:
mount_root = mount.prefix.rstrip("/") or "/"
sub_flags = _adjust_depth_flags(flag_kwargs, target_path,
mount.prefix)
if sub_flags is None:
continue
sub_texts = _adjust_depth_texts(texts, target_path, mount.prefix)
sub_paths = [
PathSpec(virtual=mount_root,
directory=mount_root,
resource_path="",
resolved=True)
]
try:
stdout, io = await mount.execute_cmd(cmd_name,
sub_paths,
sub_texts,
sub_flags,
stdin=stdin,
cwd=cwd)
except FindParseError:
# A bad numeric/size/mtime argument is a usage error that
# applies to every mount identically; fail the whole command
# instead of silently skipping mounts and exiting 0.
raise
except Exception:
continue
if mount is primary_mount and descendant_prefixes and stdout:
stdout = await _filter_under_prefixes(stdout, descendant_prefixes)
elif mount is not primary_mount and cmd_name == "find" and stdout:
stdout = await _drop_mount_root_line(stdout, mount_root)
if stdout is not None:
data = await materialize(stdout)
if data:
all_stdout.append(data)
if io.exit_code == 0:
success_seen = True
elif io.exit_code != 0 and final_exit == 0:
final_exit = io.exit_code
merged_io = await merged_io.merge(io)
if cmd_name == "find":
synthetic = _synthesize_find_mount_entries(target_path, descendants,
texts)
if synthetic:
all_stdout.append(synthetic.encode("utf-8"))
combined: ByteSource | None
if all_stdout:
combined = b"\n".join(b.rstrip(b"\n") for b in all_stdout) + b"\n"
else:
combined = None
final_io_exit = 0 if success_seen else final_exit
if cmd_name == "find":
combined, action_err = await _apply_find_actions(
combined, flag_kwargs, registry, cwd)
if action_err:
existing = (await materialize(merged_io.stderr)
if merged_io.stderr else b"")
merged_io.stderr = existing + action_err
if final_io_exit == 0:
final_io_exit = 1
merged_io.exit_code = final_io_exit
merged_io.safeguard = resolve_across_mounts(cmd_name,
[primary_mount, *descendants])
exec_node = ExecutionNode(command=cmd_str,
exit_code=final_io_exit,
stderr=merged_io.stderr)
return combined, merged_io, exec_node