agentforge-chat-history-postgres 0.2.3__tar.gz → 0.2.4__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 (13) hide show
  1. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/PKG-INFO +2 -2
  2. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/pyproject.toml +2 -2
  3. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/src/agentforge_chat_history_postgres/_inmem_runner.py +16 -1
  4. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/src/agentforge_chat_history_postgres/history.py +13 -2
  5. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/tests/unit/test_postgres_history_branches.py +6 -4
  6. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/.gitignore +0 -0
  7. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/LICENSE +0 -0
  8. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/README.md +0 -0
  9. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/src/agentforge_chat_history_postgres/__init__.py +0 -0
  10. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/src/agentforge_chat_history_postgres/_runner.py +0 -0
  11. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/src/agentforge_chat_history_postgres/py.typed +0 -0
  12. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/tests/integration/test_postgres_history_live.py +0 -0
  13. {agentforge_chat_history_postgres-0.2.3 → agentforge_chat_history_postgres-0.2.4}/tests/unit/test_postgres_history.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentforge-chat-history-postgres
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Postgres-backed ChatHistoryStore for AgentForge
5
5
  Project-URL: Homepage, https://github.com/Scaffoldic/agentforge-py
6
6
  Project-URL: Repository, https://github.com/Scaffoldic/agentforge-py
@@ -19,7 +19,7 @@ Classifier: Topic :: Database
19
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.13
22
- Requires-Dist: agentforge-core~=0.2.3
22
+ Requires-Dist: agentforge-core~=0.2.4
23
23
  Requires-Dist: asyncpg>=0.30
24
24
  Description-Content-Type: text/markdown
25
25
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  [project]
10
10
  name = "agentforge-chat-history-postgres"
11
- version = "0.2.3"
11
+ version = "0.2.4"
12
12
  description = "Postgres-backed ChatHistoryStore for AgentForge"
13
13
  readme = "README.md"
14
14
  requires-python = ">=3.13"
@@ -30,7 +30,7 @@ classifiers = [
30
30
  ]
31
31
 
32
32
  dependencies = [
33
- "agentforge-core ~= 0.2.3",
33
+ "agentforge-core ~= 0.2.4",
34
34
  "asyncpg>=0.30",
35
35
  ]
36
36
 
@@ -79,7 +79,22 @@ class PostgresFakeRunner:
79
79
  self._insert_turn(params)
80
80
  return
81
81
  if sql_n.startswith("insert into chat_sessions"):
82
- self._upsert_session(params[0], params[1])
82
+ # DO NOTHING (bug-018 create-if-missing) must not bump
83
+ # last_active_at on an existing row; DO UPDATE (append path)
84
+ # does. Mirror the real ON CONFLICT clause.
85
+ if "do nothing" in sql_n:
86
+ self._sessions.setdefault(
87
+ params[0],
88
+ {
89
+ "id": params[0],
90
+ "owner": None,
91
+ "created_at": params[1],
92
+ "last_active_at": params[1],
93
+ "metadata": {},
94
+ },
95
+ )
96
+ else:
97
+ self._upsert_session(params[0], params[1])
83
98
  return
84
99
  if sql_n.startswith("update chat_sessions set metadata"):
85
100
  metadata_json, owner, session_id = params
@@ -13,7 +13,7 @@ from __future__ import annotations
13
13
 
14
14
  import json
15
15
  from collections.abc import Mapping
16
- from datetime import datetime
16
+ from datetime import UTC, datetime
17
17
  from typing import Any
18
18
 
19
19
  from agentforge_core.contracts.chat import ChatHistoryStore
@@ -199,11 +199,22 @@ class PostgresChatHistory(ChatHistoryStore):
199
199
  return [await self._row_to_info(row) for row in rows]
200
200
 
201
201
  async def update_session_metadata(self, session_id: str, metadata: Mapping[str, Any]) -> None:
202
+ # Create the session row if it doesn't exist yet (bug-018):
203
+ # ChatServer records owner/metadata before the first turn. DO
204
+ # NOTHING leaves an existing row (and last_active_at) untouched.
205
+ await self._r.execute(
206
+ """INSERT INTO chat_sessions
207
+ (id, owner, created_at, last_active_at, metadata)
208
+ VALUES ($1, NULL, $2, $2, '{}'::jsonb)
209
+ ON CONFLICT (id) DO NOTHING""",
210
+ session_id,
211
+ datetime.now(UTC),
212
+ )
202
213
  row = await self._r.fetchrow(
203
214
  "SELECT owner, metadata FROM chat_sessions WHERE id = $1",
204
215
  session_id,
205
216
  )
206
- if row is None:
217
+ if row is None: # pragma: no cover — the INSERT above guarantees a row
207
218
  raise ModuleError(f"Cannot update metadata for unknown session {session_id!r}")
208
219
  existing: dict[str, Any] = dict(_coerce_jsonb(row["metadata"]))
209
220
  existing.update(dict(metadata))
@@ -9,7 +9,6 @@ from datetime import UTC, datetime, timedelta
9
9
  import pytest
10
10
  from agentforge_chat_history_postgres import PostgresChatHistory
11
11
  from agentforge_chat_history_postgres._inmem_runner import PostgresFakeRunner
12
- from agentforge_core.production.exceptions import ModuleError
13
12
  from agentforge_core.values.chat import ChatTurn
14
13
  from agentforge_core.values.messages import ToolCall
15
14
 
@@ -63,11 +62,14 @@ async def test_list_sessions_with_before_filter() -> None:
63
62
 
64
63
 
65
64
  @pytest.mark.asyncio
66
- async def test_update_metadata_unknown_session_raises() -> None:
65
+ async def test_update_metadata_creates_unknown_session() -> None:
66
+ """bug-018: metadata on a not-yet-existing session upserts the row
67
+ rather than raising, so ChatServer can record owner before turn 1."""
67
68
  runner = PostgresFakeRunner()
68
69
  store = await PostgresChatHistory.from_dsn("p", runner=runner)
69
- with pytest.raises(ModuleError, match="unknown session"):
70
- await store.update_session_metadata("nope", {"k": "v"})
70
+ await store.update_session_metadata("nope", {"k": "v", "owner": "u1"})
71
+ sessions = await store.list_sessions(owner="u1")
72
+ assert [s.id for s in sessions] == ["nope"]
71
73
 
72
74
 
73
75
  @pytest.mark.asyncio