llm/tests/test_fragments_cli.py
Simon Willison f740a5cbbd
Fragments (#859)
* WIP fragments: schema plus reading but not yet writing, refs #617
* Unique index on fragments.alias, refs #617
* Fragments are now persisted, added basic CLI commands
* Fragment aliases work now, refs #617
* Improved help for -f/--fragment
* Support fragment hash as well
* Documentation for fragments
* Better non-JSON display of llm fragments list
* llm fragments -q search option
* _truncate_string is now truncate_string
* Use condense_json to avoid duplicate data in JSON in DB, refs #617
* Follow up to 3 redirects for fragments
* Python API docs for fragments= and system_fragments=
* Fragment aliases cannot contain a : - this is to ensure we can add custom fragment loaders later on, refs https://github.com/simonw/llm/pull/859#issuecomment-2761534692
* Use template fragments when running prompts
* llm fragments show command plus llm fragments group tests
* Tests for fragments family of commands
* Test for --save with fragments
* Add fragments tables to docs/logging.md
* Slightly better llm fragments --help
* Handle fragments in past conversations correctly
* Hint at llm prompt --help in llm --help, closes #868
* llm logs -f filter plus show fragments in llm logs --json
* Include prompt and system fragments in llm logs -s
* llm logs markdown fragment output and tests, refs #617
2025-04-05 17:22:37 -07:00

51 lines
1.8 KiB
Python

from click.testing import CliRunner
from llm.cli import cli
import yaml
def test_fragments_set_show_remove(user_path):
runner = CliRunner()
with runner.isolated_filesystem():
open("fragment1.txt", "w").write("Hello fragment 1")
assert (
runner.invoke(cli, ["fragments", "set", "f1", "fragment1.txt"]).exit_code
== 0
)
result1 = runner.invoke(cli, ["fragments", "show", "f1"])
assert result1.exit_code == 0
assert result1.output == "Hello fragment 1\n"
# Should be in the list now
def get_list():
result2 = runner.invoke(cli, ["fragments", "list"])
assert result2.exit_code == 0
return yaml.safe_load(result2.output)
loaded1 = get_list()
assert set(loaded1[0].keys()) == {
"aliases",
"content",
"datetime_utc",
"source",
"hash",
}
assert loaded1[0]["content"] == "Hello fragment 1"
assert loaded1[0]["aliases"] == ["f1"]
# Show should work against both alias and hash
for key in ("f1", loaded1[0]["hash"]):
result3 = runner.invoke(cli, ["fragments", "show", key])
assert result3.exit_code == 0
assert result3.output == "Hello fragment 1\n"
# But not for an invalid alias
result4 = runner.invoke(cli, ["fragments", "show", "badalias"])
assert result4.exit_code == 1
assert "Fragment 'badalias' not found" in result4.output
# Remove that alias
assert runner.invoke(cli, ["fragments", "remove", "f1"]).exit_code == 0
# Should still be in list but no alias
loaded2 = get_list()
assert loaded2[0]["aliases"] == []
assert loaded2[0]["content"] == "Hello fragment 1"