agentforge-chat-http 0.2.3__tar.gz → 0.3.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.
@@ -47,3 +47,13 @@ Thumbs.db
47
47
  # Project-local
48
48
  *.local
49
49
  .agentforge-state/.session-cache
50
+
51
+ # AI-assistant working state — local session tracking, not part of
52
+ # the published project. The process docs under .claude/ (standards,
53
+ # checklists, CLAUDE.md) are intentionally kept tracked; only the
54
+ # churny per-session state files are ignored.
55
+ .claude/state/
56
+
57
+ # Launch / go-to-market drafts — local-only marketing material,
58
+ # never published to the repo.
59
+ launch/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentforge-chat-http
3
- Version: 0.2.3
3
+ Version: 0.3.0
4
4
  Summary: FastAPI HTTP + WebSocket + SSE server for AgentForge chat sessions
5
5
  Project-URL: Homepage, https://github.com/Scaffoldic/agentforge-py
6
6
  Project-URL: Repository, https://github.com/Scaffoldic/agentforge-py
@@ -18,9 +18,9 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
19
  Classifier: Typing :: Typed
20
20
  Requires-Python: >=3.13
21
- Requires-Dist: agentforge-chat~=0.2.3
22
- Requires-Dist: agentforge-core~=0.2.3
23
- Requires-Dist: agentforge-py~=0.2.3
21
+ Requires-Dist: agentforge-chat~=0.3.0
22
+ Requires-Dist: agentforge-core~=0.3.0
23
+ Requires-Dist: agentforge-py~=0.3.0
24
24
  Requires-Dist: fastapi>=0.115
25
25
  Requires-Dist: httpx>=0.27
26
26
  Requires-Dist: uvicorn>=0.32
@@ -2,7 +2,7 @@
2
2
 
3
3
  [project]
4
4
  name = "agentforge-chat-http"
5
- version = "0.2.3"
5
+ version = "0.3.0"
6
6
  description = "FastAPI HTTP + WebSocket + SSE server for AgentForge chat sessions"
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.13"
@@ -24,9 +24,9 @@ classifiers = [
24
24
  ]
25
25
 
26
26
  dependencies = [
27
- "agentforge-core ~= 0.2.3",
28
- "agentforge-py ~= 0.2.3",
29
- "agentforge-chat ~= 0.2.3",
27
+ "agentforge-core ~= 0.3.0",
28
+ "agentforge-py ~= 0.3.0",
29
+ "agentforge-chat ~= 0.3.0",
30
30
  "fastapi>=0.115",
31
31
  "uvicorn>=0.32",
32
32
  "httpx>=0.27",
@@ -281,9 +281,10 @@ class ChatServer:
281
281
  async with self._sessions_lock:
282
282
  self._sessions[session.session_id] = session
283
283
  self._session_owners[session.session_id] = principal.id
284
- # Persist an initial owner record on the store so list_sessions
285
- # filtering works before the first turn.
286
- await self._history.update_session_metadata(session.session_id, {"owner": principal.id})
284
+ # Create the session row up front so list_sessions filtering works
285
+ # before the first turn (bug-018). create_session upserts via the
286
+ # store, so this is safe on a fresh process / SQLite driver.
287
+ await self._history.create_session(session.session_id, owner=principal.id)
287
288
  return session
288
289
 
289
290
  async def _get_session(self, session_id: str, principal: Principal) -> ChatSession:
@@ -89,6 +89,35 @@ def test_create_session_returns_id(client: TestClient) -> None:
89
89
  assert "id" in r.json()
90
90
 
91
91
 
92
+ async def test_create_session_works_with_sqlite_store(monkeypatch: pytest.MonkeyPatch) -> None:
93
+ """bug-018: POST /sessions must not 500 on a fresh SQLite-backed server.
94
+ `_create_session` records the owner before the first turn; the SQLite
95
+ driver used to raise because the row didn't exist yet."""
96
+ import httpx # noqa: PLC0415
97
+ from agentforge_chat import SqliteChatHistory # noqa: PLC0415
98
+
99
+ monkeypatch.setenv("API_TOKENS", "good-token")
100
+ store = await SqliteChatHistory.from_path(":memory:")
101
+ try:
102
+ server = ChatServer(
103
+ agent_factory=_agent_factory,
104
+ history_store=store,
105
+ auth=EnvBearerAuth("API_TOKENS"),
106
+ host="127.0.0.1",
107
+ port=8080,
108
+ )
109
+ transport = httpx.ASGITransport(app=server.app)
110
+ async with httpx.AsyncClient(transport=transport, base_url="http://test") as ac:
111
+ r = await ac.post("/sessions", json={}, headers=_auth())
112
+ assert r.status_code == 200
113
+ sid = r.json()["id"]
114
+ # The session is persisted and listable before any turn.
115
+ listed = await store.list_sessions()
116
+ assert sid in {s.id for s in listed}
117
+ finally:
118
+ await store.close()
119
+
120
+
92
121
  def test_missing_bearer_returns_401(client: TestClient) -> None:
93
122
  r = client.post("/sessions", json={})
94
123
  assert r.status_code == 401