mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-17 10:13:57 +00:00
refactor: rename the application package to docsgpt
The backend import package is now docsgpt, the name it will carry on PyPI; application was far too generic to install into anyone's site-packages. git mv plus a mechanical rewrite of every import, dotted string and path reference: 734 Python files, the compose files, Dockerfile, workflows, docs, setup scripts, devcontainer, k8s manifests, vscode config, pytest and coverage config, .gitignore. Behaviour is unchanged. Kept for one release: - A top-level application package whose meta-path finder resolves application.x.y to the already-imported docsgpt.x.y object, so old imports and entry points (celery -A application.app.celery, uvicorn application.asgi:asgi_app) keep working with a FutureWarning. - Celery registers every application.* task name as an alias of its docsgpt.* task on start-up, so messages queued by the previous release still run. The redbeat key prefix moves to redbeat:docsgpt:v2: so schedule entries the previous release wrote are left unread instead of firing twice. The backend image builds from the repository root (docker build -f docsgpt/Dockerfile .) so it can ship the alias package; a root .dockerignore allow-lists docsgpt/ and application/ and keeps caches, local data, .env files, the sample index files and the Dockerfile out. Compose and the image workflows point at the new context.
This commit is contained in:
1 parent
3e7f1f91b4
commit
574f96341e
984 files changed
+9847
-9682
No files matched your search
@@ -1,5 +1,5 @@
|
||||
"""Streaming-heartbeat liveness for reasoning models that "think" before
|
||||
answering (``complete_stream`` in ``application/api/answer/routes/base.py``).
|
||||
answering (``complete_stream`` in ``docsgpt/api/answer/routes/base.py``).
|
||||
|
||||
Background
|
||||
----------
|
||||
@@ -42,10 +42,10 @@ from typing import Any, Dict, List, Optional
|
||||
import pytest
|
||||
from sqlalchemy import text
|
||||
|
||||
from application.api.answer.routes.base import BaseAnswerResource
|
||||
from application.api.answer.services.conversation_service import ConversationService
|
||||
from application.storage.db.repositories.conversations import ConversationsRepository
|
||||
from application.storage.db.repositories.reconciliation import (
|
||||
from docsgpt.api.answer.routes.base import BaseAnswerResource
|
||||
from docsgpt.api.answer.services.conversation_service import ConversationService
|
||||
from docsgpt.storage.db.repositories.conversations import ConversationsRepository
|
||||
from docsgpt.storage.db.repositories.reconciliation import (
|
||||
ReconciliationRepository,
|
||||
)
|
||||
|
||||
@@ -152,9 +152,9 @@ def _wire_db(engine, monkeypatch):
|
||||
the journal writer for a no-op. Mirrors the helper in
|
||||
``test_v1_tool_pause_finalization.py``.
|
||||
"""
|
||||
from application.api.answer.services import conversation_service as conv_mod
|
||||
from application.api.answer.services import continuation_service as cont_mod
|
||||
from application.api.answer.routes import base as base_mod
|
||||
from docsgpt.api.answer.services import conversation_service as conv_mod
|
||||
from docsgpt.api.answer.services import continuation_service as cont_mod
|
||||
from docsgpt.api.answer.routes import base as base_mod
|
||||
|
||||
@contextmanager
|
||||
def _session():
|
||||
@@ -237,7 +237,7 @@ class TestHeartbeatPumpsDuringReasoning:
|
||||
def test_thought_only_stream_heartbeats_while_pending(
|
||||
self, pg_engine, monkeypatch
|
||||
):
|
||||
from application.api.answer.routes import base as base_mod
|
||||
from docsgpt.api.answer.routes import base as base_mod
|
||||
|
||||
user_id = f"user-{uuid.uuid4().hex[:8]}"
|
||||
with pg_engine.begin() as conn:
|
||||
@@ -312,7 +312,7 @@ class TestHeartbeatPumpsDuringReasoning:
|
||||
``last_heartbeat_at`` already stamped (seed-at-start), and a subsequent
|
||||
``thought`` must bump it further — all before any ``answer``.
|
||||
"""
|
||||
from application.api.answer.routes import base as base_mod
|
||||
from docsgpt.api.answer.routes import base as base_mod
|
||||
|
||||
user_id = f"user-{uuid.uuid4().hex[:8]}"
|
||||
with pg_engine.begin() as conn:
|
||||
@@ -540,7 +540,7 @@ class TestNormalAnswerTurnUnchanged:
|
||||
def test_answer_turn_marks_streaming_and_finalizes_complete(
|
||||
self, pg_engine, monkeypatch
|
||||
):
|
||||
from application.api.answer.routes import base as base_mod
|
||||
from docsgpt.api.answer.routes import base as base_mod
|
||||
|
||||
user_id = f"user-{uuid.uuid4().hex[:8]}"
|
||||
with pg_engine.begin() as conn:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Extended unit tests for application/api/v1/routes.py.
|
||||
"""Extended unit tests for docsgpt/api/v1/routes.py.
|
||||
|
||||
Covers:
|
||||
- _extract_bearer_token helper
|
||||
@@ -18,7 +18,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from application.api.v1.routes import (
|
||||
from docsgpt.api.v1.routes import (
|
||||
_extract_bearer_token,
|
||||
_get_model_name,
|
||||
v1_bp,
|
||||
@@ -130,8 +130,8 @@ class TestChatCompletions:
|
||||
def _patch_mongo(self, monkeypatch, mongo=None):
|
||||
if mongo is None:
|
||||
mongo = self._make_mongo()
|
||||
monkeypatch.setattr("application.api.v1.routes.MongoDB.get_client", lambda: mongo)
|
||||
monkeypatch.setattr("application.api.v1.routes.settings.MONGO_DB_NAME", "testdb")
|
||||
monkeypatch.setattr("docsgpt.api.v1.routes.MongoDB.get_client", lambda: mongo)
|
||||
monkeypatch.setattr("docsgpt.api.v1.routes.settings.MONGO_DB_NAME", "testdb")
|
||||
|
||||
def test_missing_auth_returns_401(self):
|
||||
app = _build_app()
|
||||
@@ -181,7 +181,7 @@ class TestListModelsExtra:
|
||||
|
||||
@contextmanager
|
||||
def _patch_v1_db(conn):
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
|
||||
if AgentsRepository(conn).find_by_key("x") is None:
|
||||
AgentsRepository(conn).create("u-test", "Test Agent", "published", key="x")
|
||||
@@ -190,7 +190,7 @@ def _patch_v1_db(conn):
|
||||
def _yield():
|
||||
yield conn
|
||||
|
||||
with patch("application.api.v1.routes.db_readonly", _yield):
|
||||
with patch("docsgpt.api.v1.routes.db_readonly", _yield):
|
||||
yield
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ def _patch_v1_db(conn):
|
||||
def test_response_usage_reports_cumulative_turn_totals():
|
||||
from types import SimpleNamespace
|
||||
|
||||
from application.api.v1.routes import _response_usage
|
||||
from docsgpt.api.v1.routes import _response_usage
|
||||
|
||||
# Multi-round tool turns must report the accumulator's turn total,
|
||||
# not the final round's provider snapshot.
|
||||
@@ -222,8 +222,8 @@ def test_response_usage_reports_cumulative_turn_totals():
|
||||
@pytest.mark.unit
|
||||
class TestLookupAgentHappy:
|
||||
def test_returns_agent_for_valid_key(self, pg_conn):
|
||||
from application.api.v1.routes import _lookup_agent
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.api.v1.routes import _lookup_agent
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
|
||||
AgentsRepository(pg_conn).create("u1", "Test", "published", key="k-ok")
|
||||
|
||||
@@ -233,21 +233,21 @@ class TestLookupAgentHappy:
|
||||
assert got["key"] == "k-ok"
|
||||
|
||||
def test_returns_none_when_not_found(self, pg_conn):
|
||||
from application.api.v1.routes import _lookup_agent
|
||||
from docsgpt.api.v1.routes import _lookup_agent
|
||||
|
||||
with _patch_v1_db(pg_conn):
|
||||
got = _lookup_agent("nope")
|
||||
assert got is None
|
||||
|
||||
def test_returns_none_on_exception(self):
|
||||
from application.api.v1.routes import _lookup_agent
|
||||
from docsgpt.api.v1.routes import _lookup_agent
|
||||
|
||||
@contextmanager
|
||||
def _broken():
|
||||
raise RuntimeError("db down")
|
||||
yield
|
||||
|
||||
with patch("application.api.v1.routes.db_readonly", _broken):
|
||||
with patch("docsgpt.api.v1.routes.db_readonly", _broken):
|
||||
got = _lookup_agent("k")
|
||||
assert got is None
|
||||
|
||||
@@ -264,7 +264,7 @@ class TestListModelsPgConn:
|
||||
assert resp.status_code == 401
|
||||
|
||||
def test_returns_agent_for_valid_key(self, pg_conn):
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
|
||||
app = _build_app()
|
||||
repo = AgentsRepository(pg_conn)
|
||||
@@ -291,7 +291,7 @@ class TestListModelsPgConn:
|
||||
raise RuntimeError("boom")
|
||||
yield
|
||||
|
||||
with patch("application.api.v1.routes.db_readonly", _broken):
|
||||
with patch("docsgpt.api.v1.routes.db_readonly", _broken):
|
||||
with app.test_client() as c:
|
||||
resp = c.get(
|
||||
"/v1/models",
|
||||
@@ -348,10 +348,10 @@ class TestChatCompletionsHappyPath:
|
||||
"extra": {},
|
||||
}
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -368,7 +368,7 @@ class TestChatCompletionsHappyPath:
|
||||
def test_null_n_is_treated_as_default(self, pg_conn):
|
||||
app = _build_app()
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=ValueError("reached translator"),
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -400,8 +400,8 @@ class TestChatCompletionsHappyPath:
|
||||
assert resp.get_json()["error"]["type"] == "invalid_request_error"
|
||||
|
||||
def test_conversation_id_must_belong_to_authenticated_agent(self, pg_conn):
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from application.storage.db.repositories.conversations import (
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.storage.db.repositories.conversations import (
|
||||
ConversationsRepository,
|
||||
)
|
||||
|
||||
@@ -447,18 +447,18 @@ class TestChatCompletionsHappyPath:
|
||||
"extra": {},
|
||||
}
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.load_conversation",
|
||||
"docsgpt.api.v1.routes.load_conversation",
|
||||
return_value="deleted-conversation",
|
||||
), patch(
|
||||
"application.api.v1.routes._conversation_belongs_to_agent",
|
||||
"docsgpt.api.v1.routes._conversation_belongs_to_agent",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"application.api.v1.routes.delete_conversation",
|
||||
"docsgpt.api.v1.routes.delete_conversation",
|
||||
) as delete_mapping, patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -474,7 +474,7 @@ class TestChatCompletionsHappyPath:
|
||||
delete_mapping.assert_called_once()
|
||||
|
||||
def test_duplicate_resume_returns_conflict(self, pg_conn):
|
||||
from application.api.answer.services.continuation_service import (
|
||||
from docsgpt.api.answer.services.continuation_service import (
|
||||
ResumeInProgressError,
|
||||
)
|
||||
|
||||
@@ -482,20 +482,20 @@ class TestChatCompletionsHappyPath:
|
||||
fake_processor = MagicMock()
|
||||
fake_processor.decoded_token = {"sub": "u-test"}
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
return_value={
|
||||
"conversation_id": "conv-1",
|
||||
"tool_actions": [{"call_id": "call-1", "result": "ok"}],
|
||||
"messages": [],
|
||||
},
|
||||
), patch(
|
||||
"application.api.v1.routes._conversation_belongs_to_agent",
|
||||
"docsgpt.api.v1.routes._conversation_belongs_to_agent",
|
||||
return_value=True,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes.ContinuationService.claim_state",
|
||||
"docsgpt.api.v1.routes.ContinuationService.claim_state",
|
||||
side_effect=ResumeInProgressError("Resume already in progress"),
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -530,7 +530,7 @@ class TestChatCompletionsHappyPath:
|
||||
def test_translate_error_returns_400(self, pg_conn):
|
||||
app = _build_app()
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=ValueError("bad"),
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -552,10 +552,10 @@ class TestChatCompletionsHappyPath:
|
||||
}
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=MagicMock(decoded_token={"sub": "u"}),
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -576,10 +576,10 @@ class TestChatCompletionsHappyPath:
|
||||
fake_processor.build_agent.side_effect = ValueError("boom")
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -600,10 +600,10 @@ class TestChatCompletionsHappyPath:
|
||||
fake_processor.build_agent.side_effect = RuntimeError("boom")
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -645,16 +645,16 @@ class TestChatCompletionsHappyPath:
|
||||
}
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_response",
|
||||
"docsgpt.api.v1.routes.translate_response",
|
||||
return_value={"id": "x", "choices": []},
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -691,13 +691,13 @@ class TestChatCompletionsHappyPath:
|
||||
}
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -730,16 +730,16 @@ class TestChatCompletionsHappyPath:
|
||||
fake_helper.complete_stream.side_effect = _fake_helper_complete_stream
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_stream_event",
|
||||
"docsgpt.api.v1.routes.translate_stream_event",
|
||||
return_value=["data: chunk\n\n"],
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -793,16 +793,16 @@ class TestChatCompletionsHappyPath:
|
||||
fake_helper.complete_stream.side_effect = _fake_helper_complete_stream
|
||||
|
||||
with _patch_v1_db(pg_conn), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_stream_event",
|
||||
"docsgpt.api.v1.routes.translate_stream_event",
|
||||
side_effect=_fake_translate_stream_event,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
|
||||
@@ -4,7 +4,7 @@ from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from application.api.v1.session_store import (
|
||||
from docsgpt.api.v1.session_store import (
|
||||
delete_conversation,
|
||||
identify_session,
|
||||
load_conversation,
|
||||
@@ -52,10 +52,10 @@ def test_save_and_load_use_bounded_redis_ttl(monkeypatch):
|
||||
redis = MagicMock()
|
||||
redis.get.return_value = b"conv-1"
|
||||
monkeypatch.setattr(
|
||||
"application.api.v1.session_store.get_redis_instance", lambda: redis
|
||||
"docsgpt.api.v1.session_store.get_redis_instance", lambda: redis
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"application.api.v1.session_store.settings.V1_SESSION_TTL_SECONDS", 123
|
||||
"docsgpt.api.v1.session_store.settings.V1_SESSION_TTL_SECONDS", 123
|
||||
)
|
||||
session = identify_session({"X-Session-ID": "s"}, {"messages": []}, "a")
|
||||
save_conversation(session, "conv-1")
|
||||
@@ -67,7 +67,7 @@ def test_save_and_load_use_bounded_redis_ttl(monkeypatch):
|
||||
def test_delete_conversation_invalidates_stale_mapping(monkeypatch):
|
||||
redis = MagicMock()
|
||||
monkeypatch.setattr(
|
||||
"application.api.v1.session_store.get_redis_instance", lambda: redis
|
||||
"docsgpt.api.v1.session_store.get_redis_instance", lambda: redis
|
||||
)
|
||||
session = identify_session({"X-Session-ID": "s"}, {"messages": []}, "a")
|
||||
delete_conversation(session)
|
||||
|
||||
@@ -16,10 +16,10 @@ import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy import text
|
||||
|
||||
from application.api.answer.services import stream_processor as sp_mod
|
||||
from application.api.v1.routes import v1_bp
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from application.storage.db.repositories.conversations import ConversationsRepository
|
||||
from docsgpt.api.answer.services import stream_processor as sp_mod
|
||||
from docsgpt.api.v1.routes import v1_bp
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.storage.db.repositories.conversations import ConversationsRepository
|
||||
|
||||
# Reuse the route-level DB wiring + seed helpers from the tool-pause suite.
|
||||
from tests.api.v1.test_v1_tool_pause_finalization import (
|
||||
|
||||
@@ -8,7 +8,7 @@ honors a client-supplied ``Idempotency-Key`` header: a retry returns the
|
||||
|
||||
These tests pin both layers against an ephemeral Postgres (``pg_engine``):
|
||||
|
||||
- the ``application.api.v1.idempotency`` helper contract directly
|
||||
- the ``docsgpt.api.v1.idempotency`` helper contract directly
|
||||
(completed → cached, fresh-pending → 409, stale-pending → re-claim,
|
||||
non-2xx → not cached); and
|
||||
- the real ``/v1/chat/completions`` route end-to-end: the same key twice
|
||||
@@ -28,8 +28,8 @@ import pytest
|
||||
from flask import Flask
|
||||
from sqlalchemy import text
|
||||
|
||||
from application.api.v1 import idempotency as v1_idem
|
||||
from application.api.v1.idempotency import (
|
||||
from docsgpt.api.v1 import idempotency as v1_idem
|
||||
from docsgpt.api.v1.idempotency import (
|
||||
STALE_PENDING_SECONDS,
|
||||
TASK_NAME,
|
||||
claim_or_replay,
|
||||
@@ -37,7 +37,7 @@ from application.api.v1.idempotency import (
|
||||
release,
|
||||
scoped_key,
|
||||
)
|
||||
from application.api.v1.routes import v1_bp
|
||||
from docsgpt.api.v1.routes import v1_bp
|
||||
|
||||
# Reuse the route-level DB wiring + fake answering agent from the tool-pause
|
||||
# suite so a real two-POST round-trip runs against the ephemeral Postgres.
|
||||
@@ -294,7 +294,7 @@ class TestV1IdempotencyRoute:
|
||||
_CountingAnswerAgent.gen_calls = 0
|
||||
|
||||
with _wire_v1_route_db(pg_engine, monkeypatch), patch(
|
||||
"application.api.answer.services.stream_processor.StreamProcessor"
|
||||
"docsgpt.api.answer.services.stream_processor.StreamProcessor"
|
||||
".build_agent",
|
||||
self._fake_build_agent,
|
||||
):
|
||||
@@ -332,7 +332,7 @@ class TestV1IdempotencyRoute:
|
||||
_CountingAnswerAgent.gen_calls = 0
|
||||
|
||||
with _wire_v1_route_db(pg_engine, monkeypatch), patch(
|
||||
"application.api.answer.services.stream_processor.StreamProcessor"
|
||||
"docsgpt.api.answer.services.stream_processor.StreamProcessor"
|
||||
".build_agent",
|
||||
self._fake_build_agent,
|
||||
):
|
||||
@@ -359,7 +359,7 @@ class TestV1IdempotencyRoute:
|
||||
_CountingAnswerAgent.gen_calls = 0
|
||||
|
||||
with _wire_v1_route_db(pg_engine, monkeypatch), patch(
|
||||
"application.api.answer.services.stream_processor.StreamProcessor"
|
||||
"docsgpt.api.answer.services.stream_processor.StreamProcessor"
|
||||
".build_agent",
|
||||
self._fake_build_agent,
|
||||
):
|
||||
@@ -399,7 +399,7 @@ class TestV1IdempotencyRoute:
|
||||
_CountingAnswerAgent.gen_calls = 0
|
||||
|
||||
with _wire_v1_route_db(pg_engine, monkeypatch), patch(
|
||||
"application.api.answer.services.stream_processor.StreamProcessor"
|
||||
"docsgpt.api.answer.services.stream_processor.StreamProcessor"
|
||||
".build_agent",
|
||||
_build,
|
||||
):
|
||||
|
||||
@@ -51,9 +51,9 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from application.api.answer.routes.base import BaseAnswerResource
|
||||
from application.api.answer.services.conversation_service import ConversationService
|
||||
from application.api.v1.routes import v1_bp
|
||||
from docsgpt.api.answer.routes.base import BaseAnswerResource
|
||||
from docsgpt.api.answer.services.conversation_service import ConversationService
|
||||
from docsgpt.api.v1.routes import v1_bp
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -215,9 +215,9 @@ def _wire_db(engine, monkeypatch):
|
||||
so we hand out fresh connections from the same ephemeral engine and
|
||||
swap the journal writer for a no-op.
|
||||
"""
|
||||
from application.api.answer.services import conversation_service as conv_mod
|
||||
from application.api.answer.services import continuation_service as cont_mod
|
||||
from application.api.answer.routes import base as base_mod
|
||||
from docsgpt.api.answer.services import conversation_service as conv_mod
|
||||
from docsgpt.api.answer.services import continuation_service as cont_mod
|
||||
from docsgpt.api.answer.routes import base as base_mod
|
||||
|
||||
@contextmanager
|
||||
def _session():
|
||||
@@ -658,28 +658,28 @@ class TestV1ContinuationRoutesStatelessly:
|
||||
yield MagicMock()
|
||||
|
||||
with patch(
|
||||
"application.api.v1.routes._lookup_agent",
|
||||
"docsgpt.api.v1.routes._lookup_agent",
|
||||
return_value={"id": "agent-1", "name": "Agent", "user_id": "owner"},
|
||||
), patch(
|
||||
"application.api.v1.routes.ContinuationService.claim_state",
|
||||
"docsgpt.api.v1.routes.ContinuationService.claim_state",
|
||||
return_value=None,
|
||||
), patch(
|
||||
"application.api.v1.routes._conversation_belongs_to_agent",
|
||||
"docsgpt.api.v1.routes._conversation_belongs_to_agent",
|
||||
return_value=True,
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
), patch(
|
||||
"application.api.v1.routes.db_readonly",
|
||||
"docsgpt.api.v1.routes.db_readonly",
|
||||
_yield_conn,
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_response",
|
||||
"docsgpt.api.v1.routes.translate_response",
|
||||
return_value={"id": "x", "choices": []},
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -767,22 +767,22 @@ class TestV1ContinuationRoutesStatelessly:
|
||||
yield MagicMock()
|
||||
|
||||
with patch(
|
||||
"application.api.v1.routes._lookup_agent",
|
||||
"docsgpt.api.v1.routes._lookup_agent",
|
||||
return_value={"id": "agent-1", "name": "Agent", "user_id": "owner"},
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_request",
|
||||
"docsgpt.api.v1.routes.translate_request",
|
||||
side_effect=_fake_translate,
|
||||
), patch(
|
||||
"application.api.v1.routes.StreamProcessor",
|
||||
"docsgpt.api.v1.routes.StreamProcessor",
|
||||
return_value=fake_processor,
|
||||
), patch(
|
||||
"application.api.v1.routes._V1AnswerHelper",
|
||||
"docsgpt.api.v1.routes._V1AnswerHelper",
|
||||
return_value=fake_helper,
|
||||
), patch(
|
||||
"application.api.v1.routes.db_readonly",
|
||||
"docsgpt.api.v1.routes.db_readonly",
|
||||
_yield_conn,
|
||||
), patch(
|
||||
"application.api.v1.routes.translate_response",
|
||||
"docsgpt.api.v1.routes.translate_response",
|
||||
return_value={"id": "x", "choices": []},
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -888,7 +888,7 @@ class _PauseThenAnswerAgent:
|
||||
|
||||
|
||||
def _seed_agent(conn, user_id: str, key: str) -> None:
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
|
||||
AgentsRepository(conn).create(user_id, "Weather Agent", "published", key=key)
|
||||
|
||||
@@ -902,8 +902,8 @@ def _wire_v1_route_db(engine, monkeypatch):
|
||||
title-gen ``LLMCreator`` on the base module, so a real two-POST round-trip
|
||||
runs entirely against the ephemeral Postgres with no live LLM/provider.
|
||||
"""
|
||||
from application.api.v1 import routes as v1_routes_mod
|
||||
from application.api.answer.routes import base as base_mod
|
||||
from docsgpt.api.v1 import routes as v1_routes_mod
|
||||
from docsgpt.api.answer.routes import base as base_mod
|
||||
|
||||
@contextmanager
|
||||
def _readonly():
|
||||
@@ -1007,11 +1007,11 @@ class TestV1ToolRoundTripEndToEnd:
|
||||
|
||||
# ---- POST #1: user question -> agent pauses for the client tool ----
|
||||
with _wire_v1_route_db(pg_engine, monkeypatch), patch(
|
||||
"application.api.answer.services.stream_processor.StreamProcessor"
|
||||
"docsgpt.api.answer.services.stream_processor.StreamProcessor"
|
||||
".build_agent",
|
||||
_fake_build_agent,
|
||||
), patch(
|
||||
"application.api.v1.routes._conversation_belongs_to_agent",
|
||||
"docsgpt.api.v1.routes._conversation_belongs_to_agent",
|
||||
return_value=True,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
@@ -1049,11 +1049,11 @@ class TestV1ToolRoundTripEndToEnd:
|
||||
|
||||
# ---- POST #2: tool result + conversation_id -> agent answers ----
|
||||
with _wire_v1_route_db(pg_engine, monkeypatch), patch(
|
||||
"application.api.answer.services.stream_processor.StreamProcessor"
|
||||
"docsgpt.api.answer.services.stream_processor.StreamProcessor"
|
||||
".build_agent",
|
||||
_fake_build_agent,
|
||||
), patch(
|
||||
"application.api.v1.routes._conversation_belongs_to_agent",
|
||||
"docsgpt.api.v1.routes._conversation_belongs_to_agent",
|
||||
return_value=True,
|
||||
):
|
||||
with app.test_client() as c:
|
||||
|
||||
Reference in new issue
Block a user