Connector calls, semantic rules, and DuckDB memory keep long runs stable, and stream retry stops chats from stalling. Co-authored-by: Cursor <cursoragent@cursor.com>
190 lines
6.4 KiB
Python
190 lines
6.4 KiB
Python
from kamidso.assistant.context_builder import DEFAULT_BEHAVIOR, KamidsoContextBuilder
|
|
from kamidso.contracts.user import CurrentUser
|
|
|
|
|
|
def _user() -> CurrentUser:
|
|
return CurrentUser(
|
|
id="usr_test",
|
|
email="test@example.com",
|
|
name="Test",
|
|
role="user",
|
|
workspace_id="ws_test",
|
|
)
|
|
|
|
|
|
def test_default_behavior_identifies_as_kamidso():
|
|
assert "Kamidso" in DEFAULT_BEHAVIOR
|
|
assert "کامیدسو" in DEFAULT_BEHAVIOR
|
|
assert "Never say you are DB-GPT" in DEFAULT_BEHAVIOR
|
|
|
|
|
|
def test_default_behavior_targets_managers_not_chatgpt():
|
|
assert "organization, the company" in DEFAULT_BEHAVIOR
|
|
assert "managers and decision-makers" in DEFAULT_BEHAVIOR
|
|
assert "ChatGPT" in DEFAULT_BEHAVIOR
|
|
assert "concise" not in DEFAULT_BEHAVIOR
|
|
|
|
|
|
def test_default_behavior_requires_numeric_precision():
|
|
assert "Numeric precision" in DEFAULT_BEHAVIOR
|
|
assert "Never compute in your head" in DEFAULT_BEHAVIOR
|
|
assert "Never mix units" in DEFAULT_BEHAVIOR
|
|
assert "Parts must add up to the total" in DEFAULT_BEHAVIOR
|
|
assert "source, filters, Jalali time range" in DEFAULT_BEHAVIOR
|
|
assert "numerator and the denominator" in DEFAULT_BEHAVIOR
|
|
assert "Count distinct entities" in DEFAULT_BEHAVIOR
|
|
assert "Do not present a sample" in DEFAULT_BEHAVIOR
|
|
assert "check every number" in DEFAULT_BEHAVIOR
|
|
|
|
|
|
def test_default_behavior_is_thorough_even_without_a_skill():
|
|
assert "Even when no skill runs" in DEFAULT_BEHAVIOR
|
|
assert "tables of figures" in DEFAULT_BEHAVIOR
|
|
assert "mapped" in DEFAULT_BEHAVIOR
|
|
assert "hypotheses" in DEFAULT_BEHAVIOR
|
|
assert "causes" in DEFAULT_BEHAVIOR
|
|
assert "optimal decision options" in DEFAULT_BEHAVIOR
|
|
assert "executive summary" not in DEFAULT_BEHAVIOR.lower()
|
|
assert "follow that skill's output structure" in DEFAULT_BEHAVIOR
|
|
|
|
|
|
def test_files_without_report_use_full_agent_not_auto_skill():
|
|
ctx = KamidsoContextBuilder().build(_user(), files=["file_1"])
|
|
assert ctx.skills == []
|
|
|
|
|
|
def test_selected_skill_with_files_is_optional_hint():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
skill="root-cause-investigator",
|
|
files=["file_1"],
|
|
)
|
|
assert ctx.skills == ["root-cause-investigator"]
|
|
assert "root-cause-investigator" in ctx.behavior
|
|
assert "optional hint" in ctx.behavior
|
|
assert "MUST be `load_skill`" not in ctx.behavior
|
|
assert "Do NOT skip the skill" not in ctx.behavior
|
|
|
|
|
|
def test_files_report_mode_does_not_force_a_skill():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
files=["file_1"],
|
|
analysis_mode="report",
|
|
)
|
|
assert ctx.skills == []
|
|
|
|
|
|
def test_files_keep_named_skill_when_explicit():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
skill="sales-intelligence",
|
|
files=["file_1"],
|
|
)
|
|
assert ctx.skills == ["sales-intelligence"]
|
|
|
|
|
|
def test_attached_knowledge_is_named_in_behavior():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
knowledge=["kb_1"],
|
|
ext_info={"knowledge_space_label": "پاسخ فنی واحد معاملات"},
|
|
)
|
|
assert "پاسخ فنی واحد معاملات" in ctx.behavior
|
|
assert "knowledge space is attached" in ctx.behavior
|
|
|
|
|
|
def test_attached_database_is_primary_source():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
datasources=["sqlite_Walmart_Sales"],
|
|
ext_info={"database_label": "Walmart Sales"},
|
|
)
|
|
assert ctx.skills == []
|
|
assert "database()" in ctx.behavior
|
|
assert "code_interpreter" in ctx.behavior
|
|
assert "Walmart Sales" in ctx.behavior
|
|
assert "Excel/CSV" in ctx.behavior
|
|
assert "count" in ctx.behavior.lower()
|
|
assert "never pull a large table" in ctx.behavior.lower()
|
|
assert "Do not call `sql_query`" in ctx.behavior
|
|
|
|
|
|
def test_explicit_database_skill_is_kept():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
skill="sales-intelligence",
|
|
datasources=["mongo_ops"],
|
|
)
|
|
assert ctx.skills == ["sales-intelligence"]
|
|
|
|
|
|
def test_multiple_attached_databases_are_named():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
datasources=["ds_1", "ds_2"],
|
|
files=["file_1"],
|
|
ext_info={"database_labels": ["فروش", "عملیات"]},
|
|
)
|
|
assert ctx.skills == []
|
|
assert "فروش" in ctx.behavior
|
|
assert "عملیات" in ctx.behavior
|
|
assert "Pass `source=`" in ctx.behavior
|
|
assert "code_interpreter" in ctx.behavior
|
|
assert "database()" in ctx.behavior
|
|
assert "Do not reopen Excel/CSV" not in ctx.behavior
|
|
|
|
|
|
def test_no_attached_source_forbids_leftover_runtime_files():
|
|
ctx = KamidsoContextBuilder().build(_user())
|
|
assert ctx.skills == []
|
|
assert "No file or database is attached this turn" in ctx.behavior
|
|
assert "data/runtime" in ctx.behavior
|
|
assert "question tool" in ctx.behavior
|
|
|
|
|
|
def test_files_only_forbid_sql_and_database_question():
|
|
ctx = KamidsoContextBuilder().build(_user(), files=["file_1"])
|
|
assert "File(s) are attached this turn" in ctx.behavior
|
|
assert "Do NOT call `sql_query`" in ctx.behavior
|
|
assert "Do NOT ask which database" in ctx.behavior
|
|
assert "No file or database is attached this turn" not in ctx.behavior
|
|
|
|
|
|
def test_selected_skill_appends_settings_and_rule_pack_instructions():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
skill="iran-payroll-compliance",
|
|
skill_context="Legal Rule Pack IR-1405 v1.0",
|
|
)
|
|
assert ctx.skills == ["iran-payroll-compliance"]
|
|
assert "optional hint" in ctx.behavior
|
|
assert "IR-1405" in ctx.behavior
|
|
assert "Article 38" in ctx.behavior
|
|
|
|
|
|
def test_connector_only_does_not_claim_nothing_is_attached():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
ext_info={
|
|
"connector_ids": ["didar-a"],
|
|
"connector_labels": ["دیدار فروش"],
|
|
},
|
|
)
|
|
assert "No file or database is attached this turn" not in ctx.behavior
|
|
assert "connector_call" in ctx.behavior
|
|
assert "دیدار فروش" in ctx.behavior
|
|
assert "validation_error" in ctx.behavior
|
|
|
|
|
|
def test_connector_with_file_keeps_both_sources():
|
|
ctx = KamidsoContextBuilder().build(
|
|
_user(),
|
|
files=["file_1"],
|
|
ext_info={"connector_ids": ["didar-a"], "connector_labels": ["دیدار فروش"]},
|
|
)
|
|
assert "File(s) are attached this turn" in ctx.behavior
|
|
assert "connector_call" in ctx.behavior
|
|
assert "code_interpreter" in ctx.behavior
|
|
|