MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / expand_at_mentions

Function expand_at_mentions

src/command_system/input_processing.py:485–622  ·  view source on GitHub ↗

Resolve ``@path`` mentions and build context attachments. Mirrors ``processAtMentionedFiles`` in ``typescript/src/utils/attachments.ts``: if a mention resolves to a directory we build a ``Listed directory`` attachment containing its entries (up to 1000); if it resolves to a readable

(
    text: str,
    *,
    cwd: str | None = None,
)

Source from the content-addressed store, hash-verified

483
484
485def expand_at_mentions(
486 text: str,
487 *,
488 cwd: str | None = None,
489) -> tuple[str, list[dict[str, Any]]]:
490 """Resolve ``@path`` mentions and build context attachments.
491
492 Mirrors ``processAtMentionedFiles`` in
493 ``typescript/src/utils/attachments.ts``: if a mention resolves to a
494 directory we build a ``Listed directory`` attachment containing its
495 entries (up to 1000); if it resolves to a readable image file
496 (png/jpg/jpeg/gif/webp) we attach a ``kind="image"`` attachment with
497 base64 + media_type via the image pipeline, so the REPL can inline it
498 as a real image content block in the user message instead of mojibake
499 in a system-reminder. Other readable files we attach the
500 file's contents verbatim. The returned ``text`` is left unchanged — the
501 caller prepends / appends the attachments before sending to the model.
502 """
503 cwd = cwd or os.getcwd()
504 seen: set[str] = set()
505 attachments: list[dict[str, Any]] = []
506
507 for match in _FILE_MENTION_RE.finditer(text):
508 raw = match.group(1).rstrip(".,!?:;\"'`)]}")
509 if not raw:
510 continue
511 # Skip bare @word mentions (no path separator / dot / home marker).
512 if not (
513 raw.startswith(("/", "~", "./", "../"))
514 or "/" in raw
515 or "." in raw
516 ):
517 continue
518
519 # C5: the search dialog inserts ``@file#Lline`` (TS
520 # attachments.ts:2859-2861 parses the ``#L10-20`` fragment).
521 # Degraded port: strip the fragment so the FILE attaches — the
522 # line reference stays visible to the model in the prompt text;
523 # range slicing is a noted follow-up.
524 fragment_match = re.search(r"#L\d+(?:-\d+)?$", raw)
525 if fragment_match:
526 raw = raw[: fragment_match.start()]
527 if not raw:
528 continue
529
530 expanded = os.path.expanduser(raw)
531 if not os.path.isabs(expanded):
532 expanded = os.path.abspath(os.path.join(cwd, expanded))
533 if expanded in seen:
534 continue
535 seen.add(expanded)
536
537 try:
538 if os.path.isdir(expanded):
539 entries = sorted(os.listdir(expanded))
540 truncated = len(entries) > _MAX_DIR_ENTRIES
541 shown = entries[:_MAX_DIR_ENTRIES]
542 if truncated:

Calls 9

_looks_like_binaryFunction · 0.85
_binary_hint_for_extFunction · 0.85
_read_text_with_encodingFunction · 0.85
searchMethod · 0.80
joinMethod · 0.80
startMethod · 0.45
addMethod · 0.45
appendMethod · 0.45