@@ -73,7 +73,7 @@ from ai_web_agent_console.query_contracts import (
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
MCP_PROTOCOL_VERSION = "2025-11-25"
|
||||
PREFERRED_TOOL = "search_hr_data"
|
||||
PREFERRED_TOOL = "oracle.select_ai.smilegate_game_text2sql"
|
||||
DEFAULT_QUESTION = ""
|
||||
MAX_RESPONSE_BYTES = 1_000_000
|
||||
MAX_CONVERSATION_MESSAGES = 8
|
||||
@@ -91,15 +91,21 @@ DEFAULT_QUERY_MODEL_PROFILE = "gpt54_mini_oci"
|
||||
ENV_FILE = ROOT / ".env"
|
||||
MCP_SERVERS_FILE = ROOT / "config" / "mcp_servers.json"
|
||||
VPD_TOKEN_PRESETS_FILE = ROOT / "config" / "vpd_token_presets.json"
|
||||
DEMO_SCENARIOS_FILE = ROOT / "config" / "hmm_demo_scenarios.json"
|
||||
DEMO_SCENARIOS_FILE = ROOT / "config" / "smilegate_demo_scenarios.json"
|
||||
APP_PROFILE_FILE = ROOT / "config" / "app_profile.json"
|
||||
CHAT_DB_FILE = ROOT / "data" / "poc4_mcp_chat.sqlite3"
|
||||
DEFAULT_VPD_USER_ID = "E1001"
|
||||
VPD_OPERATIONS_URL = "https://hmm-backoffice.cloud-handson.com/"
|
||||
DEFAULT_VPD_USER_ID = "sg-teamlead"
|
||||
VPD_OPERATIONS_URL = "https://smilegate-backoffice.cloud-handson.com/"
|
||||
PORTAL_AUTHENTICATED_KEY = "poc4_portal_authenticated"
|
||||
PORTAL_AUTH_USER_KEY = "poc4_portal_auth_user"
|
||||
PORTAL_AUTH_PROXY_USER_HEADER = "X-HMM-Authenticated-User"
|
||||
PORTAL_AUTH_PROXY_EXPIRY_HEADER = "X-HMM-Auth-Expires"
|
||||
PORTAL_LOGIN_FAILURE_KEY = "poc4_portal_login_failed"
|
||||
PORTAL_REMEMBER_TOKEN_PARAM = "poc4_remember"
|
||||
PORTAL_REMEMBER_MAX_AGE_SECONDS = 7 * 24 * 60 * 60
|
||||
AUDIT_SCHEMA = "SGMP_POC"
|
||||
REFERENCE_EVIDENCE_ENABLED = (
|
||||
os.environ.get("POC4_REFERENCE_EVIDENCE_ENABLED", "").strip().lower()
|
||||
in {"1", "true", "yes"}
|
||||
)
|
||||
AUDIT_DB_ENV_FILE = Path(
|
||||
os.environ.get("AI_WEB_AGENT_CONSOLE_AUDIT_DB_ENV_FILE")
|
||||
or os.environ.get("POC4_AUDIT_DB_ENV_FILE")
|
||||
@@ -918,6 +924,8 @@ def collect_security_evidence(
|
||||
) -> Mapping[str, Any]:
|
||||
"""Collect predefined, token-scoped security evidence without exposing secrets."""
|
||||
|
||||
if not REFERENCE_EVIDENCE_ENABLED:
|
||||
return {}
|
||||
kind = _security_evidence_kind(question)
|
||||
if not kind or token_preset is None:
|
||||
return {}
|
||||
@@ -1482,6 +1490,8 @@ def collect_business_evidence(
|
||||
) -> Mapping[str, Any]:
|
||||
"""Collect token-validated, explicitly scoped business and catalog evidence."""
|
||||
|
||||
if not REFERENCE_EVIDENCE_ENABLED:
|
||||
return {}
|
||||
kind = _business_evidence_kind(question)
|
||||
if not kind or token_preset is None:
|
||||
return {}
|
||||
@@ -5578,13 +5588,10 @@ def main() -> None:
|
||||
)
|
||||
else:
|
||||
selected_token_preset = None
|
||||
selected_preset_bearer = (
|
||||
selected_token_preset.token if selected_token_preset is not None else ""
|
||||
)
|
||||
if configured_mcp_bearer or selected_preset_bearer:
|
||||
# The HMM MCP gateway credential is never rendered. Each demo-user
|
||||
# preset refers to its runtime env key, allowing secure profile swaps.
|
||||
st.caption("MCP 인증: 선택 사용자 preset의 서버 관리 토큰 적용")
|
||||
if configured_mcp_bearer:
|
||||
# The Smilegate MCP gateway uses a server-side credential. UI-only
|
||||
# context must never be forwarded as a second bearer token.
|
||||
st.caption("MCP 인증: 서버 관리 토큰 적용")
|
||||
manual_bearer_token = ""
|
||||
elif selected_token_preset is not None:
|
||||
manual_bearer_token = st.text_input(
|
||||
@@ -5765,9 +5772,7 @@ def main() -> None:
|
||||
'<div id="kb-main-tabs-anchor" style="scroll-margin-top: 0.75rem;"></div>',
|
||||
unsafe_allow_html=True,
|
||||
)
|
||||
architecture_tab, scenario_tab, audit_tab, operations_tab = st.tabs(
|
||||
["아키텍처", "시나리오", "감사로그", "보안관리"]
|
||||
)
|
||||
architecture_tab, scenario_tab = st.tabs(["아키텍처", "시나리오"])
|
||||
with architecture_tab:
|
||||
_render_architecture_tab()
|
||||
|
||||
@@ -5868,17 +5873,6 @@ def main() -> None:
|
||||
height=0,
|
||||
)
|
||||
|
||||
with audit_tab:
|
||||
render_hmm_audit_tab(
|
||||
st,
|
||||
_load_hmm_audit_inventory,
|
||||
_load_hmm_audit_events,
|
||||
AuditLogError,
|
||||
)
|
||||
|
||||
with operations_tab:
|
||||
_render_vpd_operations_tab()
|
||||
|
||||
if not submitted:
|
||||
return
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"version": 1,
|
||||
"product": {
|
||||
"name": "AI 업무 에이전트",
|
||||
"short_name": "AGENT",
|
||||
"page_title": "AI 업무 에이전트",
|
||||
"name": "SMILEGATE DATA & AI POC",
|
||||
"short_name": "SMILEGATE",
|
||||
"page_title": "SMILEGATE DATA & AI POC",
|
||||
"page_icon": "🤖",
|
||||
"header_title": "AI 업무 에이전트",
|
||||
"header_description": "사용자 권한에 맞는 업무 질의와 보안 관리 기능을 제공합니다.",
|
||||
"login_kicker": "DATA & AI DEMO",
|
||||
"login_title": "AI 업무 에이전트",
|
||||
"login_description": "사용자 인증 후 업무 질의와 보안 관리 기능을 이용할 수 있습니다.",
|
||||
"login_footer": "인증된 DEMO 사용자만 접근할 수 있습니다."
|
||||
"header_title": "스마일게이트 게임 데이터 AI 에이전트",
|
||||
"header_description": "게임 로그·서비스 데이터를 기반으로 AI 업무 효율화와 데이터 플랫폼 활용 방식을 검증합니다.",
|
||||
"login_kicker": "SMILEGATE DATA & AI POC",
|
||||
"login_title": "스마일게이트 게임 데이터 AI 에이전트",
|
||||
"login_description": "사용자 인증 후 게임 데이터 AI 질의와 보안 관리 기능을 이용할 수 있습니다.",
|
||||
"login_footer": "승인된 Data & AI PoC 사용자만 접근할 수 있습니다."
|
||||
},
|
||||
"theme": {
|
||||
"primary_color": "#003b70",
|
||||
"text_color": "#172b3a",
|
||||
"muted_color": "#667785",
|
||||
"border_color": "#dfe7ed"
|
||||
"primary_color": "#113F67",
|
||||
"text_color": "#15283B",
|
||||
"muted_color": "#5D6C7C",
|
||||
"border_color": "#D7E0E8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
{
|
||||
"default_server_id": "hmm_hr_mcp",
|
||||
"default_server_id": "smilegate_game_data_mcp",
|
||||
"servers": [
|
||||
{
|
||||
"id": "hmm_hr_mcp",
|
||||
"id": "smilegate_game_data_mcp",
|
||||
"enabled": true,
|
||||
"provider": "hmm_compat_mcp",
|
||||
"provider": "smilegate_select_ai_mcp",
|
||||
"transport": "http",
|
||||
"endpoint_url": "https://hmm-mcp.cloud-handson.com/mcp",
|
||||
"auth_token_env": "HMM_MCP_BEARER_TOKEN",
|
||||
"timeout_seconds_env": "AI_WEB_AGENT_CONSOLE_MCP_TIMEOUT_SECONDS",
|
||||
"default_tool": "search_hr_data",
|
||||
"endpoint_url": "https://smilegate-backoffice.cloud-handson.com/mcp",
|
||||
"auth_token_env": "SMILEGATE_MCP_BEARER_TOKEN",
|
||||
"timeout_seconds_env": "POC3_MCP_TIMEOUT_SECONDS",
|
||||
"default_tool": "oracle.select_ai.smilegate_game_text2sql",
|
||||
"router_model_profile": "gpt54_mini_oci",
|
||||
"tool_allowlist": [
|
||||
"search_hr_data",
|
||||
"resolve_hr_term",
|
||||
"search_hr_policy",
|
||||
"search_carrier_performance"
|
||||
"oracle.select_ai.smilegate_game_text2sql"
|
||||
],
|
||||
"description": "HMM HR knowledge, ADB employee assignment, and RDS carrier performance MCP server"
|
||||
"description": "Smilegate game-data Text2SQL MCP server"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
41
ai-web-agent-console/config/smilegate_demo_scenarios.json
Normal file
41
ai-web-agent-console/config/smilegate_demo_scenarios.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"version": 1,
|
||||
"description": "Smilegate Data & AI PoC 화면에 표시할 게임 데이터 질의 샘플입니다.",
|
||||
"scenarios": [
|
||||
{
|
||||
"id": "GAME-01",
|
||||
"enabled": true,
|
||||
"category": "활성 사용자",
|
||||
"title": "카제나 최신 AU",
|
||||
"question": "카제나 최신 기준 활성 사용자 수(AU)를 알려줘"
|
||||
},
|
||||
{
|
||||
"id": "GAME-02",
|
||||
"enabled": true,
|
||||
"category": "매출",
|
||||
"title": "게임별 판매 현황",
|
||||
"question": "최신 기준 게임별 판매 건수와 판매 금액을 보여줘"
|
||||
},
|
||||
{
|
||||
"id": "GAME-03",
|
||||
"enabled": true,
|
||||
"category": "환불",
|
||||
"title": "최근 환불 현황",
|
||||
"question": "최신 기준 게임별 환불 건수와 환불 금액을 보여줘"
|
||||
},
|
||||
{
|
||||
"id": "GAME-04",
|
||||
"enabled": true,
|
||||
"category": "게임·서버",
|
||||
"title": "게임 서버 구성",
|
||||
"question": "등록된 게임과 게임 서버 정보를 보여줘"
|
||||
},
|
||||
{
|
||||
"id": "GAME-05",
|
||||
"enabled": true,
|
||||
"category": "사용자 분석",
|
||||
"title": "신규 사용자 현황",
|
||||
"question": "최신 월 기준 게임별 신규 사용자 수를 보여줘"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,52 +1,14 @@
|
||||
{
|
||||
"version": 2,
|
||||
"description": "HMM HR 데모 사용자 선택 목록입니다. 파일명은 기존 배포 호환성을 위해 유지합니다. token 원문은 저장하지 않고 mcp_token_env의 서버 환경변수만 참조합니다.",
|
||||
"presets": [
|
||||
{
|
||||
"enabled": true,
|
||||
"enabled": false,
|
||||
"default": true,
|
||||
"mcp_token_env": "HMM_MCP_BEARER_TOKEN",
|
||||
"user_id": "E1001",
|
||||
"name": "Kim Minseo",
|
||||
"role": "HR Team Manager",
|
||||
"team": "HMM HR Demo Team",
|
||||
"scope": "팀원 6명의 휴가·근태 현황을 확인하는 관리자 데모"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"mcp_token_env": "HMM_MCP_BEARER_TOKEN",
|
||||
"user_id": "E1002",
|
||||
"name": "Lee Jiwon",
|
||||
"role": "HR Operations Specialist",
|
||||
"team": "HMM HR Demo Team",
|
||||
"scope": "본인 휴가 잔여·신청·근태를 확인하는 팀원 데모"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"mcp_token_env": "HMM_MCP_BEARER_TOKEN",
|
||||
"user_id": "E1003",
|
||||
"name": "Park Dohyun",
|
||||
"role": "People Analytics Analyst",
|
||||
"team": "HMM HR Demo Team",
|
||||
"scope": "본인 휴가·근태와 팀 인력 현황을 확인하는 분석 담당 데모"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"mcp_token_env": "HMM_MCP_BEARER_TOKEN",
|
||||
"user_id": "E1005",
|
||||
"name": "Han Seojun",
|
||||
"role": "Recruiting Specialist",
|
||||
"team": "HMM HR Demo Team",
|
||||
"scope": "대기 중인 2일 연차 신청을 확인하는 팀원 데모"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"mcp_token_env": "HMM_MCP_BEARER_TOKEN",
|
||||
"user_id": "E1007",
|
||||
"name": "Kang Minho",
|
||||
"role": "HR Coordinator",
|
||||
"team": "HMM HR Demo Team",
|
||||
"scope": "대기 중인 1일 연차 신청과 휴가 근태를 확인하는 팀원 데모"
|
||||
"token": "vpd_live_REPLACE_WITH_USER_TOKEN",
|
||||
"user_id": "FC00789",
|
||||
"name": "김설계",
|
||||
"role": "설계사",
|
||||
"channel": "설계사",
|
||||
"scope": "본인 담당 계약 고객"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,134 +6,44 @@ import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from ai_web_agent_console.scenarios import ScenarioConfigError, load_demo_scenarios
|
||||
from ai_web_agent_console.profile import load_app_profile
|
||||
from ai_web_agent_console.mcp_tool_router import McpTool, build_mcp_tool_arguments
|
||||
from ai_web_agent_console.mcp_result import (
|
||||
has_actionable_text_result,
|
||||
status_result_evidence,
|
||||
status_result_summary,
|
||||
)
|
||||
from ai_web_agent_console.model_registry import load_model_registry
|
||||
|
||||
|
||||
def _load_console_query_helpers():
|
||||
"""Load the Streamlit entrypoint only when its optional runtime is installed."""
|
||||
|
||||
try:
|
||||
from app import _prepare_hmm_hr_tool_query
|
||||
except ModuleNotFoundError:
|
||||
return None
|
||||
return _prepare_hmm_hr_tool_query
|
||||
from src.poc4.scenarios import ScenarioConfigError, load_demo_scenarios
|
||||
from src.agent_console.profile import load_app_profile
|
||||
|
||||
|
||||
class DemoScenarioConfigTest(unittest.TestCase):
|
||||
def test_model_registry_uses_console_names(self) -> None:
|
||||
registry = load_model_registry()
|
||||
|
||||
self.assertEqual(
|
||||
registry.registry_name,
|
||||
"AI_WEB_AGENT_CONSOLE_MODEL_PROFILES",
|
||||
)
|
||||
self.assertTrue(registry.default_profile.default_for_console)
|
||||
|
||||
def test_profile_environment_overrides_json_defaults(self) -> None:
|
||||
path = Path(__file__).parents[1] / "config" / "app_profile.json"
|
||||
with patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"AGENT_CONSOLE_SHORT_NAME": "HMM",
|
||||
"AGENT_CONSOLE_PAGE_TITLE": "HMM AI 업무 에이전트",
|
||||
"AGENT_CONSOLE_PRIMARY_COLOR": "#003b70",
|
||||
"AGENT_CONSOLE_SHORT_NAME": "SMILEGATE",
|
||||
"AGENT_CONSOLE_PAGE_TITLE": "SMILEGATE DATA & AI POC",
|
||||
"AGENT_CONSOLE_PRIMARY_COLOR": "#113F67",
|
||||
},
|
||||
clear=False,
|
||||
):
|
||||
profile = load_app_profile(path)
|
||||
|
||||
self.assertEqual(profile.short_name, "HMM")
|
||||
self.assertEqual(profile.page_title, "HMM AI 업무 에이전트")
|
||||
self.assertEqual(profile.primary_color, "#003b70")
|
||||
self.assertEqual(profile.short_name, "SMILEGATE")
|
||||
self.assertEqual(profile.page_title, "SMILEGATE DATA & AI POC")
|
||||
self.assertEqual(profile.primary_color, "#113F67")
|
||||
|
||||
def test_profile_reads_dotenv_values(self) -> None:
|
||||
path = Path(__file__).parents[1] / "config" / "app_profile.json"
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
env_file = Path(temp_dir) / ".env"
|
||||
env_file.write_text("AGENT_CONSOLE_SHORT_NAME=HMM\n", encoding="utf-8")
|
||||
env_file.write_text("AGENT_CONSOLE_SHORT_NAME=SMILEGATE\n", encoding="utf-8")
|
||||
profile = load_app_profile(path, env_file)
|
||||
|
||||
self.assertEqual(profile.short_name, "HMM")
|
||||
self.assertEqual(profile.short_name, "SMILEGATE")
|
||||
|
||||
def test_common_theme_covers_lists_expanders_and_secondary_buttons(self) -> None:
|
||||
path = Path(__file__).parents[1] / "ai_web_agent_console" / "presentation.py"
|
||||
source = path.read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn('[data-testid="stAppViewContainer"] li', source)
|
||||
self.assertIn('[data-testid="stExpander"] summary', source)
|
||||
self.assertIn('div[data-testid="stButton"] > button', source)
|
||||
self.assertIn('[data-baseweb="tab-list"] [role="tab"]', source)
|
||||
self.assertIn('[data-testid="stTab"]', source)
|
||||
self.assertIn('[role="tab"][aria-selected="true"]', source)
|
||||
|
||||
def test_audit_tab_uses_hmm_access_audit_loaders(self) -> None:
|
||||
root = Path(__file__).parents[1]
|
||||
entrypoint = (root / "app.py").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
renderer = (root / "ai_web_agent_console" / "audit.py").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
self.assertIn("FROM ADMIN.HMM_ACCESS_AUDIT", entrypoint)
|
||||
self.assertIn("_load_hmm_audit_inventory", entrypoint)
|
||||
self.assertIn("(protocol=tcps)(port=1521)", entrypoint)
|
||||
self.assertIn(
|
||||
"AI_WEB_AGENT_CONSOLE_AUDIT_WALLET_PASSWORD",
|
||||
entrypoint,
|
||||
)
|
||||
self.assertIn("HMM 접근 관리", renderer)
|
||||
self.assertNotIn('AUDIT_SCHEMA = "POC_2"', entrypoint)
|
||||
|
||||
def test_hmm_scenarios_are_enabled_and_unique(self) -> None:
|
||||
path = Path(__file__).parents[1] / "config" / "hmm_demo_scenarios.json"
|
||||
def test_smilegate_scenarios_are_enabled_and_unique(self) -> None:
|
||||
path = Path(__file__).parents[1] / "config" / "smilegate_demo_scenarios.json"
|
||||
scenarios = load_demo_scenarios(path)
|
||||
|
||||
self.assertGreaterEqual(len(scenarios), 3)
|
||||
self.assertEqual(len(scenarios), len({item.scenario_id for item in scenarios}))
|
||||
self.assertTrue(all(item.question.strip() for item in scenarios))
|
||||
by_id = {item.scenario_id: item for item in scenarios}
|
||||
self.assertEqual(
|
||||
{"FED-01", "FED-02", "FED-03"},
|
||||
{"FED-01", "FED-02", "FED-03"} & set(by_id),
|
||||
)
|
||||
self.assertTrue(
|
||||
all("선사" in by_id[scenario_id].question for scenario_id in (
|
||||
"FED-01", "FED-02", "FED-03"
|
||||
))
|
||||
)
|
||||
|
||||
def test_hmm_mcp_allows_carrier_federation_tool(self) -> None:
|
||||
path = Path(__file__).parents[1] / "config" / "mcp_servers.json"
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
server = next(
|
||||
item for item in payload["servers"] if item["id"] == "hmm_hr_mcp"
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"search_carrier_performance",
|
||||
server["tool_allowlist"],
|
||||
)
|
||||
|
||||
def test_hmm_demo_user_presets_reference_runtime_token_only(self) -> None:
|
||||
path = Path(__file__).parents[1] / "config" / "vpd_token_presets.json"
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
presets = payload["presets"]
|
||||
|
||||
self.assertEqual(payload["version"], 2)
|
||||
self.assertEqual({item["user_id"] for item in presets}, {
|
||||
"E1001", "E1002", "E1003", "E1005", "E1007"
|
||||
})
|
||||
self.assertTrue(all(item["mcp_token_env"] == "HMM_MCP_BEARER_TOKEN" for item in presets))
|
||||
self.assertTrue(all("token" not in item for item in presets))
|
||||
|
||||
def test_duplicate_id_is_rejected(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
@@ -152,87 +62,6 @@ class DemoScenarioConfigTest(unittest.TestCase):
|
||||
with self.assertRaises(ScenarioConfigError):
|
||||
load_demo_scenarios(path)
|
||||
|
||||
def test_default_mcp_tool_arguments_follow_discovered_query_schema(self) -> None:
|
||||
tool = McpTool(
|
||||
name="search_hr_data",
|
||||
description="",
|
||||
schema={
|
||||
"type": "object",
|
||||
"properties": {"query": {"type": "string"}},
|
||||
"required": ["query"],
|
||||
},
|
||||
read_only=True,
|
||||
)
|
||||
|
||||
arguments = build_mcp_tool_arguments(
|
||||
tool, "직원 E1005의 휴가 신청 내역", 50, preferred_tool="search_hr_data"
|
||||
)
|
||||
|
||||
self.assertEqual(arguments, {"query": "직원 E1005의 휴가 신청 내역"})
|
||||
|
||||
def test_term_tool_arguments_follow_discovered_term_schema(self) -> None:
|
||||
tool = McpTool(
|
||||
name="resolve_hr_term",
|
||||
description="",
|
||||
schema={
|
||||
"type": "object",
|
||||
"properties": {"term": {"type": "string"}},
|
||||
"required": ["term"],
|
||||
},
|
||||
read_only=True,
|
||||
)
|
||||
|
||||
arguments = build_mcp_tool_arguments(
|
||||
tool, "반차", 50, preferred_tool="search_hr_data"
|
||||
)
|
||||
|
||||
self.assertEqual(arguments, {"term": "반차"})
|
||||
|
||||
def test_status_result_policy_text_is_preserved_as_answer_evidence(self) -> None:
|
||||
result = {
|
||||
"status": "success",
|
||||
"result": (
|
||||
"HR_POLICY_SEARCH_RESULT\n"
|
||||
"EVIDENCE|file=KR_Leave_Policy.pdf|chunk=13|text=이월 기준"
|
||||
),
|
||||
}
|
||||
|
||||
summary = status_result_summary(result, excerpt_chars=40)
|
||||
evidence = status_result_evidence(result)
|
||||
|
||||
self.assertEqual(summary["status"], "success")
|
||||
self.assertGreater(summary["result_chars"], 40)
|
||||
self.assertIn("KR_Leave_Policy.pdf", evidence["result"])
|
||||
self.assertTrue(has_actionable_text_result(result))
|
||||
|
||||
def test_no_data_text_is_not_actionable(self) -> None:
|
||||
self.assertFalse(
|
||||
has_actionable_text_result({"status": "success", "result": "No data found"})
|
||||
)
|
||||
|
||||
@unittest.skipIf(_load_console_query_helpers() is None, "Streamlit runtime is optional")
|
||||
def test_policy_query_does_not_include_demo_user_context(self) -> None:
|
||||
prepare = _load_console_query_helpers()
|
||||
assert prepare is not None
|
||||
tool = McpTool(
|
||||
name="search_hr_policy",
|
||||
description="Search policy documents",
|
||||
schema={"properties": {"query": {"type": "string"}}},
|
||||
read_only=True,
|
||||
)
|
||||
|
||||
query = prepare(
|
||||
question="연차 휴가 이월 기준과 제한을 알려줘",
|
||||
tool=tool,
|
||||
model_profile_key="gpt54_mini_oci",
|
||||
selected_user_id="E1001",
|
||||
selected_user_role="HR Team Manager",
|
||||
selected_user_team="HMM HR Demo Team",
|
||||
selected_user_scope="팀원 6명 관리",
|
||||
)
|
||||
|
||||
self.assertEqual(query, "연차 휴가 이월 기준과 제한을 알려줘")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user