From f498727a8cc83edf115e372c696ca08f36c2bded Mon Sep 17 00:00:00 2001 From: ajspig Date: Tue, 18 Aug 2026 12:59:56 -0400 Subject: [PATCH] feat(sdk): removing parent_id in favor of source_id since a conclusion can have many parents --- sdks/python/src/honcho/aio.py | 5 +++-- sdks/python/src/honcho/conclusions.py | 5 +++-- sdks/typescript/__tests__/conclusions.test.ts | 4 ++-- sdks/typescript/src/conclusions.ts | 5 +++-- src/utils/filter.py | 1 - tests/routes/test_conclusions.py | 14 +++++++------- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/sdks/python/src/honcho/aio.py b/sdks/python/src/honcho/aio.py index c70bf56b..76cdb6ce 100644 --- a/sdks/python/src/honcho/aio.py +++ b/sdks/python/src/honcho/aio.py @@ -1758,7 +1758,8 @@ class ConclusionScopeAio: size: Number of results per page. Default: 50. reverse: If True, reverses the default newest-first ordering. - Equivalent to ``list`` with a ``parent_id`` filter, restricted to this + Equivalent to ``list`` with + ``{"source_ids": {"contains": conclusion_id}}``, restricted to this observer/observed pair. An unknown ``conclusion_id`` yields an empty page rather than an error. @@ -1768,7 +1769,7 @@ class ConclusionScopeAio: return await _alist_conclusions( self._scope._honcho, { - "parent_id": conclusion_id, + "source_ids": {"contains": conclusion_id}, "observer_id": self._scope.observer, "observed_id": self._scope.observed, }, diff --git a/sdks/python/src/honcho/conclusions.py b/sdks/python/src/honcho/conclusions.py index d3ec4620..23870c8e 100644 --- a/sdks/python/src/honcho/conclusions.py +++ b/sdks/python/src/honcho/conclusions.py @@ -520,7 +520,8 @@ class ConclusionScope: size: Number of results per page. Default: 50. reverse: If True, reverses the default newest-first ordering. - Equivalent to ``list`` with a ``parent_id`` filter, restricted to this + Equivalent to ``list`` with + ``{"source_ids": {"contains": conclusion_id}}``, restricted to this observer/observed pair. An unknown ``conclusion_id`` yields an empty page rather than an error. @@ -530,7 +531,7 @@ class ConclusionScope: return _list_conclusions( self._honcho, { - "parent_id": conclusion_id, + "source_ids": {"contains": conclusion_id}, "observer_id": self.observer, "observed_id": self.observed, }, diff --git a/sdks/typescript/__tests__/conclusions.test.ts b/sdks/typescript/__tests__/conclusions.test.ts index c0a7d67b..1dc7694b 100644 --- a/sdks/typescript/__tests__/conclusions.test.ts +++ b/sdks/typescript/__tests__/conclusions.test.ts @@ -398,7 +398,7 @@ describe('Conclusions', () => { }) // =========================================================================== - // Derived Conclusions (list + parent_id filter) + // Derived Conclusions (list + source_ids contains) // =========================================================================== describe('honcho.conclusions (workspace-wide)', () => { @@ -456,7 +456,7 @@ describe('Conclusions', () => { }) }) - describe('derived() via parent_id filter', () => { + describe('derived() via source_ids contains', () => { test('leaf conclusion has no derived conclusions', async () => { const peer = await client.peer('derived-conclusion-peer', { metadata: {} }) const session = await client.session('derived-conclusion-session', { metadata: {} }) diff --git a/sdks/typescript/src/conclusions.ts b/sdks/typescript/src/conclusions.ts index 69502041..7194635b 100644 --- a/sdks/typescript/src/conclusions.ts +++ b/sdks/typescript/src/conclusions.ts @@ -236,10 +236,11 @@ export class ConclusionScope { reverse?: boolean } ): Promise> { - // Equivalent to list with a parent_id filter, restricted to this pair. + // Equivalent to list with { source_ids: { contains: id } }, restricted + // to this pair. return this._list({ filters: { - parent_id: conclusionId, + source_ids: { contains: conclusionId }, observer_id: this.observer, observed_id: this.observed, }, diff --git a/src/utils/filter.py b/src/utils/filter.py index f21f1814..b2c362ea 100644 --- a/src/utils/filter.py +++ b/src/utils/filter.py @@ -74,7 +74,6 @@ ALLOWED_EXTERNAL_TO_INTERNAL_COLUMN_MAPPING_DOCUMENTS = { "observed_id": "observed", "level": "level", "source_ids": "source_ids", - "parent_id": "source_ids", "times_derived": "times_derived", "metadata": "internal_metadata", } diff --git a/tests/routes/test_conclusions.py b/tests/routes/test_conclusions.py index 534b1d99..21eb940d 100644 --- a/tests/routes/test_conclusions.py +++ b/tests/routes/test_conclusions.py @@ -1687,7 +1687,7 @@ class TestConclusionRoutes: db_session: AsyncSession, sample_data: tuple[Workspace, Peer], ): - """Test traversing the reasoning tree upward via the parent_id filter""" + """Test traversing the reasoning DAG upward via source_ids membership""" test_workspace, test_peer = sample_data test_peer2 = models.Peer( @@ -1706,7 +1706,7 @@ class TestConclusionRoutes: response = client.post( f"/v3/workspaces/{test_workspace.name}/conclusions/list", - json={"filters": {"parent_id": premise.id}}, + json={"filters": {"source_ids": {"contains": premise.id}}}, ) assert response.status_code == 200 @@ -1725,7 +1725,7 @@ class TestConclusionRoutes: # derived1 is itself a source of derived2 response = client.post( f"/v3/workspaces/{test_workspace.name}/conclusions/list", - json={"filters": {"parent_id": derived1.id}}, + json={"filters": {"source_ids": {"contains": derived1.id}}}, ) assert response.status_code == 200 data = response.json() @@ -1758,7 +1758,7 @@ class TestConclusionRoutes: response = client.post( f"/v3/workspaces/{test_workspace.name}/conclusions/list", params={"reverse": "true"}, - json={"filters": {"parent_id": premise.id}}, + json={"filters": {"source_ids": {"contains": premise.id}}}, ) assert response.status_code == 200 @@ -1791,7 +1791,7 @@ class TestConclusionRoutes: response = client.post( f"/v3/workspaces/{test_workspace.name}/conclusions/list", - json={"filters": {"parent_id": derived2.id}}, + json={"filters": {"source_ids": {"contains": derived2.id}}}, ) assert response.status_code == 200 @@ -1805,12 +1805,12 @@ class TestConclusionRoutes: client: TestClient, sample_data: tuple[Workspace, Peer], ): - """A nonexistent parent yields an empty page, not an error""" + """A nonexistent source id yields an empty page, not an error.""" test_workspace, _test_peer = sample_data response = client.post( f"/v3/workspaces/{test_workspace.name}/conclusions/list", - json={"filters": {"parent_id": str(generate_nanoid())}}, + json={"filters": {"source_ids": {"contains": str(generate_nanoid())}}}, ) assert response.status_code == 200