honcho-cli 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/CHANGELOG.md +9 -1
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/PKG-INFO +2 -2
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/pyproject.toml +2 -2
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/__init__.py +1 -1
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/conclusion.py +18 -5
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_conclusion_attribution.py +39 -1
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/uv.lock +5 -5
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/.gitignore +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/README.md +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/scripts/generate_cli_docs.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/_help.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/agents.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/branding.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/__init__.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/config_cmd.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/install.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/message.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/peer.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/scope.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/session.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/setup.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/stack.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/workspace.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/common.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/config.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/__init__.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/docker.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/env.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/health.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/profile.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/setup.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/templates/__init__.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/templates/docker-compose.yml +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/templates/init.sql +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/main.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/oauth.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/output.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/recall.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/update_check.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/validation.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/__init__.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/conftest.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_commands.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_common.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_config.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_install.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_local.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_oauth.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_output.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_recall.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_setup.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_start.py +0 -0
- {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_validation.py +0 -0
|
@@ -5,7 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.4.0] - 2026-10-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `source_message_ids` on conclusion output: the messages an explicit conclusion cites as evidence (Honcho v3.5.0+; a count in table mode, the full list in JSON). `conclusion list --cites <message_id>` narrows to the conclusions that cite a message. Null in JSON on servers or SDKs that predate the field (#935)
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Requires `honcho-ai` 2.8.0 or newer, the first Python SDK that carries `source_message_ids`
|
|
9
17
|
|
|
10
18
|
## [0.3.0] - 2026-10-23
|
|
11
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: honcho-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A terminal for Honcho — memory that reasons.
|
|
5
5
|
Project-URL: Homepage, https://github.com/plastic-labs/honcho
|
|
6
6
|
Project-URL: Repository, https://github.com/plastic-labs/honcho
|
|
@@ -15,7 +15,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
15
15
|
Requires-Python: >=3.11
|
|
16
16
|
Requires-Dist: certifi>=2026.10.19
|
|
17
17
|
Requires-Dist: click>=8.0.0
|
|
18
|
-
Requires-Dist: honcho-ai>=2.
|
|
18
|
+
Requires-Dist: honcho-ai>=2.8.0
|
|
19
19
|
Requires-Dist: httpx>=0.27.0
|
|
20
20
|
Requires-Dist: questionary>=2.1.0
|
|
21
21
|
Requires-Dist: rich>=13.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "honcho-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
description = "A terminal for Honcho — memory that reasons."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -19,7 +19,7 @@ classifiers = [
|
|
|
19
19
|
dependencies = [
|
|
20
20
|
"click>=8.0.0",
|
|
21
21
|
"typer>=0.15.0",
|
|
22
|
-
"honcho-ai>=2.
|
|
22
|
+
"honcho-ai>=2.8.0",
|
|
23
23
|
"rich>=13.0.0",
|
|
24
24
|
"httpx>=0.27.0",
|
|
25
25
|
"questionary>=2.1.0",
|
|
@@ -21,23 +21,29 @@ add_common_options(app)
|
|
|
21
21
|
_LEVELS = ("explicit", "deductive", "inductive", "contradiction")
|
|
22
22
|
|
|
23
23
|
#: Columns carrying a conclusion's attribution, shown alongside the content.
|
|
24
|
-
_ATTRIBUTION_COLUMNS = ["id", "level", "source_ids", "times_derived", "content"]
|
|
24
|
+
_ATTRIBUTION_COLUMNS = ["id", "level", "source_ids", "source_message_ids", "times_derived", "content"]
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def _format_conclusion(c, workspace_id: str | None) -> dict:
|
|
28
28
|
"""Shape a Conclusion for output.
|
|
29
29
|
|
|
30
30
|
``level``, ``source_ids`` and ``times_derived`` are the attribution the
|
|
31
|
-
server started returning in Honcho v3.2.0
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
server started returning in Honcho v3.2.0; ``source_message_ids`` (the
|
|
32
|
+
messages an explicit conclusion cites) arrived in v3.5.0 and is read
|
|
33
|
+
leniently so older SDKs still work. In table mode the id lists collapse
|
|
34
|
+
to counts, since nanoids make the row unreadable; JSON mode keeps them so
|
|
35
|
+
they can be piped back into ``honcho conclusion get`` or ``message get``.
|
|
35
36
|
"""
|
|
36
37
|
source_ids = c.source_ids or []
|
|
38
|
+
# JSON keeps None ("no citation record") apart from [] ("cites nothing").
|
|
39
|
+
source_message_ids = getattr(c, "source_message_ids", None)
|
|
37
40
|
return {
|
|
38
41
|
"id": c.id,
|
|
39
42
|
"level": c.level,
|
|
40
43
|
"source_ids": source_ids if use_json() else len(source_ids),
|
|
44
|
+
"source_message_ids": source_message_ids
|
|
45
|
+
if use_json()
|
|
46
|
+
else len(source_message_ids or []),
|
|
41
47
|
"times_derived": c.times_derived,
|
|
42
48
|
"content": c.content if use_json() else c.content[:160],
|
|
43
49
|
"workspace_id": workspace_id,
|
|
@@ -86,6 +92,11 @@ def list_conclusions(
|
|
|
86
92
|
"--derived-from",
|
|
87
93
|
help="Only conclusions derived from this conclusion ID",
|
|
88
94
|
),
|
|
95
|
+
cites: Optional[str] = typer.Option(
|
|
96
|
+
None,
|
|
97
|
+
"--cites",
|
|
98
|
+
help="Only explicit conclusions that cite this message ID as evidence",
|
|
99
|
+
),
|
|
89
100
|
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
|
90
101
|
peer: Optional[str] = typer.Option(None, "--peer", "-p", help="Override peer ID"),
|
|
91
102
|
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
|
@@ -104,6 +115,8 @@ def list_conclusions(
|
|
|
104
115
|
filters["level"] = level
|
|
105
116
|
if derived_from:
|
|
106
117
|
filters["source_ids"] = {"contains": derived_from}
|
|
118
|
+
if cites:
|
|
119
|
+
filters["source_message_ids"] = {"contains": cites}
|
|
107
120
|
|
|
108
121
|
try:
|
|
109
122
|
if observed:
|
|
@@ -32,12 +32,18 @@ def runner():
|
|
|
32
32
|
return CliRunner()
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def _conclusion(
|
|
35
|
+
def _conclusion(
|
|
36
|
+
cid: str,
|
|
37
|
+
level: str = "inductive",
|
|
38
|
+
source_ids: list[str] | None = None,
|
|
39
|
+
source_message_ids: list[str] | None = None,
|
|
40
|
+
) -> MagicMock:
|
|
36
41
|
return MagicMock(
|
|
37
42
|
id=cid,
|
|
38
43
|
content=f"content for {cid}",
|
|
39
44
|
level=level,
|
|
40
45
|
source_ids=source_ids if source_ids is not None else ["p1", "p2"],
|
|
46
|
+
source_message_ids=source_message_ids,
|
|
41
47
|
times_derived=3,
|
|
42
48
|
observer_id="alice",
|
|
43
49
|
observed_id="alice",
|
|
@@ -59,10 +65,42 @@ class TestConclusionAttribution:
|
|
|
59
65
|
row = json.loads(result.stdout)[0]
|
|
60
66
|
assert row["level"] == "inductive"
|
|
61
67
|
assert row["source_ids"] == ["p1", "p2"]
|
|
68
|
+
assert row["source_message_ids"] is None
|
|
62
69
|
assert row["times_derived"] == 3
|
|
63
70
|
# --level reaches the server as a filter rather than being applied locally
|
|
64
71
|
assert client.peer.return_value.conclusions.list.call_args.kwargs["filters"] == {"level": "inductive"}
|
|
65
72
|
|
|
73
|
+
def test_list_reports_cited_messages_and_filters_by_them(self, cfg, runner):
|
|
74
|
+
client = MagicMock()
|
|
75
|
+
config = MagicMock(workspace_id="ws1", peer_id="alice")
|
|
76
|
+
client.peer.return_value.conclusions.list.return_value = MagicMock(
|
|
77
|
+
items=[_conclusion("c1", level="explicit", source_ids=[], source_message_ids=["m1", "m2"])]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
with patch("honcho_cli.commands.conclusion.get_client", return_value=(client, config)):
|
|
81
|
+
result = runner.invoke(app, ["conclusion", "list", "--cites", "m1", "-p", "alice"])
|
|
82
|
+
|
|
83
|
+
assert result.exit_code == 0
|
|
84
|
+
row = json.loads(result.stdout)[0]
|
|
85
|
+
assert row["source_message_ids"] == ["m1", "m2"]
|
|
86
|
+
assert client.peer.return_value.conclusions.list.call_args.kwargs["filters"] == {
|
|
87
|
+
"source_message_ids": {"contains": "m1"}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def test_list_tolerates_sdks_without_source_message_ids(self, cfg, runner):
|
|
91
|
+
"""An SDK predating the field must not break the listing."""
|
|
92
|
+
client = MagicMock()
|
|
93
|
+
config = MagicMock(workspace_id="ws1", peer_id="alice")
|
|
94
|
+
legacy = _conclusion("c1", level="explicit", source_ids=[])
|
|
95
|
+
del legacy.source_message_ids
|
|
96
|
+
client.peer.return_value.conclusions.list.return_value = MagicMock(items=[legacy])
|
|
97
|
+
|
|
98
|
+
with patch("honcho_cli.commands.conclusion.get_client", return_value=(client, config)):
|
|
99
|
+
result = runner.invoke(app, ["conclusion", "list", "-p", "alice"])
|
|
100
|
+
|
|
101
|
+
assert result.exit_code == 0
|
|
102
|
+
assert json.loads(result.stdout)[0]["source_message_ids"] is None
|
|
103
|
+
|
|
66
104
|
def test_list_rejects_an_unknown_level(self, cfg, runner):
|
|
67
105
|
result = runner.invoke(app, ["conclusion", "list", "--level", "nonsense", "-p", "alice"])
|
|
68
106
|
assert result.exit_code == 1
|
|
@@ -74,21 +74,21 @@ wheels = [
|
|
|
74
74
|
|
|
75
75
|
[[package]]
|
|
76
76
|
name = "honcho-ai"
|
|
77
|
-
version = "2.0
|
|
77
|
+
version = "2.6.0"
|
|
78
78
|
source = { registry = "https://pypi.org/simple" }
|
|
79
79
|
dependencies = [
|
|
80
80
|
{ name = "httpx" },
|
|
81
81
|
{ name = "pydantic" },
|
|
82
82
|
{ name = "typing-extensions", marker = "python_full_version < '3.12'" },
|
|
83
83
|
]
|
|
84
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
84
|
+
sdist = { url = "https://files.pythonhosted.org/packages/26/a7/13ad4c1b66d1a96ac66ce8cbb6e7d4d4f91cd0c4380b00caca8d27e273eb/honcho_ai-2.6.0.tar.gz", hash = "sha256:a799eb9fd3f02e34fb2a4166d8262ed407e02d276ad446e68affb370be45e47c", size = 68183, upload-time = "2026-10-14T16:30:28.525Z" }
|
|
85
85
|
wheels = [
|
|
86
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
86
|
+
{ url = "https://files.pythonhosted.org/packages/16/a5/e95f89a29b519e9e0293281b7fd8b6333c72ce44be8707cca4e452ac224e/honcho_ai-2.6.0-py3-none-any.whl", hash = "sha256:819cdd5775ecae69f617b14d60c3ea3c6ac9404b3821fa50cbf0b681aa2283cf", size = 79216, upload-time = "2026-10-14T16:30:27.211Z" },
|
|
87
87
|
]
|
|
88
88
|
|
|
89
89
|
[[package]]
|
|
90
90
|
name = "honcho-cli"
|
|
91
|
-
version = "0.
|
|
91
|
+
version = "0.2.0"
|
|
92
92
|
source = { editable = "." }
|
|
93
93
|
dependencies = [
|
|
94
94
|
{ name = "click" },
|
|
@@ -107,7 +107,7 @@ dev = [
|
|
|
107
107
|
[package.metadata]
|
|
108
108
|
requires-dist = [
|
|
109
109
|
{ name = "click", specifier = ">=8.0.0" },
|
|
110
|
-
{ name = "honcho-ai", specifier = ">=
|
|
110
|
+
{ name = "honcho-ai", specifier = ">=2.5.0" },
|
|
111
111
|
{ name = "httpx", specifier = ">=0.27.0" },
|
|
112
112
|
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0" },
|
|
113
113
|
{ name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.14.0" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|