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.
Files changed (53) hide show
  1. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/CHANGELOG.md +9 -1
  2. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/PKG-INFO +2 -2
  3. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/pyproject.toml +2 -2
  4. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/__init__.py +1 -1
  5. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/conclusion.py +18 -5
  6. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_conclusion_attribution.py +39 -1
  7. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/uv.lock +5 -5
  8. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/.gitignore +0 -0
  9. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/README.md +0 -0
  10. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/scripts/generate_cli_docs.py +0 -0
  11. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/_help.py +0 -0
  12. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/agents.py +0 -0
  13. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/branding.py +0 -0
  14. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/__init__.py +0 -0
  15. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/config_cmd.py +0 -0
  16. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/install.py +0 -0
  17. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/message.py +0 -0
  18. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/peer.py +0 -0
  19. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/scope.py +0 -0
  20. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/session.py +0 -0
  21. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/setup.py +0 -0
  22. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/stack.py +0 -0
  23. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/commands/workspace.py +0 -0
  24. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/common.py +0 -0
  25. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/config.py +0 -0
  26. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/__init__.py +0 -0
  27. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/docker.py +0 -0
  28. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/env.py +0 -0
  29. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/health.py +0 -0
  30. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/profile.py +0 -0
  31. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/setup.py +0 -0
  32. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/templates/__init__.py +0 -0
  33. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/templates/docker-compose.yml +0 -0
  34. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/local/templates/init.sql +0 -0
  35. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/main.py +0 -0
  36. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/oauth.py +0 -0
  37. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/output.py +0 -0
  38. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/recall.py +0 -0
  39. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/update_check.py +0 -0
  40. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/src/honcho_cli/validation.py +0 -0
  41. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/__init__.py +0 -0
  42. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/conftest.py +0 -0
  43. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_commands.py +0 -0
  44. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_common.py +0 -0
  45. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_config.py +0 -0
  46. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_install.py +0 -0
  47. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_local.py +0 -0
  48. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_oauth.py +0 -0
  49. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_output.py +0 -0
  50. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_recall.py +0 -0
  51. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_setup.py +0 -0
  52. {honcho_cli-0.3.0 → honcho_cli-0.4.0}/tests/test_start.py +0 -0
  53. {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
- ## [Unreleased]
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.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.5.0
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.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.5.0",
22
+ "honcho-ai>=2.8.0",
23
23
  "rich>=13.0.0",
24
24
  "httpx>=0.27.0",
25
25
  "questionary>=2.1.0",
@@ -1,3 +1,3 @@
1
1
  """Honcho CLI — a terminal for Honcho."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.4.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. In table mode ``source_ids``
32
- collapses to a count, since the ids are nanoids and a list of them makes
33
- the row unreadable; JSON mode keeps the full list so it can be piped back
34
- into ``honcho conclusion get``.
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(cid: str, level: str = "inductive", source_ids: list[str] | None = None) -> MagicMock:
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.1"
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/93/30/d30ba159404050d53b4b1b1c4477f9591f43af18758be1fb7dab6afbfe7d/honcho_ai-2.0.1.tar.gz", hash = "sha256:6fdeebf9454e62bc523d57888e50359e67baafdb21f68621f9c14e08dc00623a", size = 46732, upload-time = "2026-02-09T21:03:26.99Z" }
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/e2/de/83fda0c057cfa11d6b5ed532623184591aa7dcff4a067934ba6811026229/honcho_ai-2.0.1-py3-none-any.whl", hash = "sha256:94887e61d59f353e1e1e20b395858040780f5d67ca1e9d450538646544e4e42f", size = 56780, upload-time = "2026-02-09T21:03:25.992Z" },
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.1.1"
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 = ">=0.1.0" },
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