mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 15:37:55 +08:00
core/cli+config: attach files to a turn with @path mentions
Typing `@shot.png` in the line attaches that picture to the turn — no separate command — and `@notes.txt` appends the file as text under a `--- @path ---` header, capped like a tool result with a resumable `truncate_token`. `@"my shot.png"` is the quoted form, and Tab completes the path after `@` (directories end in `/`, a name with a space completes quoted). An image is skipped, with a note naming the key to set, on a model without `image_in`; a missing or denylisted path is a note too, and the turn still goes. The default catalogs mark what can take a picture (`deepseek-flash` yes, `deepseek-v4-pro` no, the OpenAI defaults yes). `Agent.run` takes the parts, so the turn is stored with its images and shows up as `[image]` wherever only prose is wanted.
This commit is contained in:
@@ -170,6 +170,46 @@ def test_completer_stream_on_off(tmp_path: object, monkeypatch: object) -> None:
|
||||
assert completer("o", 1) == "off"
|
||||
|
||||
|
||||
def test_completer_path_mentions(tmp_path: object, monkeypatch: object) -> None:
|
||||
"""An ``@path`` token completes files, wherever it sits in the line."""
|
||||
import readline
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
assert isinstance(tmp_path, Path)
|
||||
assert isinstance(monkeypatch, pytest.MonkeyPatch)
|
||||
(tmp_path / "shot.png").write_bytes(b"")
|
||||
(tmp_path / "screens").mkdir()
|
||||
|
||||
state = _minimal_state(tmp_path)
|
||||
completer = build_completer(state)
|
||||
monkeypatch.setattr(readline, "get_line_buffer", lambda: "look at @sh")
|
||||
monkeypatch.setattr(readline, "get_begidx", lambda: len("look at "))
|
||||
monkeypatch.chdir(tmp_path)
|
||||
|
||||
found = [item for index in range(10) if (item := completer("@sh", index)) is not None]
|
||||
assert found == ["@shot.png"]
|
||||
|
||||
|
||||
def test_a_plain_word_is_still_a_slash_argument(tmp_path: object, monkeypatch: object) -> None:
|
||||
"""The mention branch must not swallow ordinary argument completion."""
|
||||
import readline
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
assert isinstance(tmp_path, Path)
|
||||
assert isinstance(monkeypatch, pytest.MonkeyPatch)
|
||||
|
||||
state = _minimal_state(tmp_path)
|
||||
completer = build_completer(state)
|
||||
monkeypatch.setattr(readline, "get_line_buffer", lambda: "/provider r")
|
||||
monkeypatch.setattr(readline, "get_begidx", lambda: len("/provider "))
|
||||
|
||||
assert completer("r", 0) == "remote"
|
||||
|
||||
|
||||
def test_complete_slash_args_from_registry(tmp_path: object) -> None:
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
Reference in New Issue
Block a user