Skip to content

Commit b8c1cdd

Browse files
committed
gui dps
1 parent 1aa8493 commit b8c1cdd

23 files changed

Lines changed: 3366 additions & 1630 deletions

.clinerules

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
## File Reading
99
- You never need permission to read a file or analyze file.
10+
- Please make sure to read all nessesary files while working in "Plan" mode. Because I use more powerful model for "Plan" mode and less powerful for "Act".
1011

1112
## Custom instructions
1213
- Promise to follow the custom instructions.
@@ -33,6 +34,20 @@
3334
- Install with "uv add" not "pip install" or "uv pip install" etc.
3435
- This repo use uv for running all scripts - use "uv run python ...", etc.
3536

37+
## Plan vs Act Behavior
38+
39+
- During the **planning phase**, the system must:
40+
41+
* Fully analyze and examine all necessary project files.
42+
* Collect all relevant context, dependencies, and summaries required for the next steps.
43+
* Ensure that the plan includes all data the acting phase will need to operate without re-analysis.
44+
45+
- When transitioning from **Plan** to **Act**:
46+
47+
* Since Plan and Act mode handled by different AI model, Pass all essential context, reasoning results, and detailed plans to the acting model.
48+
* The acting model should **not re-read or re-analyze** files unless strictly needed for small corrections or adjustments.
49+
* The acting model should focus on implementing, refining, or correcting code according to the plan.
50+
3651
## Plan Mode
3752
- When starting to plan, show that you've understood the question by saying "Hmmm...". If not, ask more questions to clarify.
3853
- Analyze all code files thoroughly.
@@ -41,6 +56,7 @@
4156
- List all assumptions and uncertainties you need to clear up before writing code.
4257
- Give a confidence rating. On a scale of 1 to 10, how confident are you in this solution?
4358
- Think. Is this an elegant solution to this problem? Is the code easy to read? Is the code maintainable? Does the code integrate well with other parts of the project.
59+
- Carefully stick with the task.
4460

4561
## Act Mode
4662
- Always give a summary of code that's changed using snippets, unless otherwise asked.
@@ -51,9 +67,6 @@
5167
## Flet
5268
- When answering questions about Flet refer to the /resources/flet-docs folder.
5369

54-
## Tree
55-
- On a weekly basis, or anytime the project tree changes, check that the project tree matches the tree specified in @docs/technical/project_folder_structure.md
56-
5770
## Database model
5871
- On a weekly basis, or anytime the database model changes, check that the database model in @db/models.py matches the docs in @docs/technical/dpd_headwords_table.md
5972

db_tests/dps_internal_tests.tsv

Lines changed: 121 additions & 0 deletions
Large diffs are not rendered by default.

gui/functions_dps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ def translate_with_ai(dpspth, meaning_in, lemma_1, grammar, pos, notes, suggesti
344344
translation_example = pos_example_map.get(pos, "")
345345

346346
if provider == "openai":
347-
model = "gpt-4o-2024-08-06"
347+
model = "gpt-4o-mini"
348348
elif provider == "deepseek":
349349
model = "deepseek-chat"
350350
grammar_orig = grammar

gui2/data/daily_log.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,5 +810,11 @@
810810
"pass2_add": 7,
811811
"pass2_pre": 0,
812812
"pass2_update": 64
813+
},
814+
"2025-10-19": {
815+
"pass1": 0,
816+
"pass2_add": 0,
817+
"pass2_pre": 0,
818+
"pass2_update": 3
813819
}
814820
}

gui2/data/dps_history.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"id": 48511,
4+
"lemma_1": "buddha 1"
5+
},
6+
{
7+
"id": 34554,
8+
"lemma_1": "dhanatthika"
9+
},
10+
{
11+
"id": 1442,
12+
"lemma_1": "ajjhohata"
13+
},
14+
{
15+
"id": 48512,
16+
"lemma_1": "buddha 2"
17+
},
18+
{
19+
"id": 1234,
20+
"lemma_1": "ajjattanī"
21+
}
22+
]

gui2/data/example_stash.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@
1010
"example": "taṃ sabbaṃ saṅghabhedakkhandhake (cūḷava. 343) āgatam'eva. pañcavatthuyācanā pana kiñ'c'āpi tatth'eva āgamissati. atha kho idhā'pi āgatattā yadettha vattabbaṃ, taṃ vatvāva gamissāma."
1111
},
1212
"stash": {
13-
"source": "UDa30",
14-
"sutta": "lokasuttavaṇṇanā",
15-
"example": "pariḷāhehī'ti paridāhehi. pariḍayhamāne'ti indhanaṃ viya agginā samantato ḍayhamāne."
13+
"source": "MN116",
14+
"sutta": "isigilisuttaṃ",
15+
"example": "bhūtapubbaṃ, bhikkhave, pañca paccekabuddhasatāni imasmiṃ isigilismiṃ pabbate ciranivāsino ahesuṃ. te imaṃ pabbataṃ pavisantā dissanti, paviṭṭhā na dissanti."
16+
},
17+
"dps_shared": {
18+
"source": "SN10.8",
19+
"sutta": "sudattasuttaṃ",
20+
"example": "buddho kira loke uppanno"
1621
}
1722
}

gui2/data/history.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
11
[
2+
{
3+
"id": 48512,
4+
"lemma_1": "buddha 2"
5+
},
6+
{
7+
"id": 12353,
8+
"lemma_1": "ārakkhādhikaraṇaṃ"
9+
},
10+
{
11+
"id": 48511,
12+
"lemma_1": "buddha 1"
13+
},
214
{
315
"id": 83842,
416
"lemma_1": "pādapaṃsu"
@@ -66,17 +78,5 @@
6678
{
6779
"id": 85363,
6880
"lemma_1": "ganthika"
69-
},
70-
{
71-
"id": 85379,
72-
"lemma_1": "paharaṇa 3"
73-
},
74-
{
75-
"id": 17330,
76-
"lemma_1": "ūnodara"
77-
},
78-
{
79-
"id": 85451,
80-
"lemma_1": "milāyana"
8181
}
8282
]

gui2/database_manager.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
FamilyRoot,
1212
FamilyWord,
1313
InflectionTemplates,
14+
Russian,
15+
SBS,
1416
Lookup,
1517
)
1618
from gui2.dpd_fields_functions import clean_lemma_1
@@ -416,6 +418,16 @@ def get_headword_by_id_or_lemma(self, user_input: str) -> DpdHeadword | None:
416418

417419
# --- DB FUNCTIONS ---
418420

421+
def fetch_ru(self, id: int) -> Russian | None:
422+
"""Fetch Russian word from db."""
423+
return self.db_session.query(Russian).filter(
424+
Russian.id == id).first()
425+
426+
def fetch_sbs(self, id: int) -> SBS | None:
427+
"""Fetch SBS word from db."""
428+
return self.db_session.query(SBS).filter(
429+
SBS.id == id).first()
430+
419431
def add_word_to_db(self, new_word):
420432
try:
421433
self.db_session.add(new_word)

gui2/dps_ai_cli_wrapper.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/usr/bin/env python3
2+
"""CLI wrapper for AI translation - runs AI in separate process without interactive input"""
3+
4+
import subprocess
5+
import sys
6+
import os
7+
8+
9+
def run_ai_via_subprocess(headword_id: int, mode: str, synonyms: bool = False, provider: str = "openai") -> str:
10+
"""
11+
Run AI translation via subprocess to avoid signal conflicts.
12+
13+
Args:
14+
headword_id: Headword ID to translate
15+
mode: "meaning" or "note"
16+
provider: AI provider ("openai" or "deepseek")
17+
18+
Returns:
19+
AI-generated suggestion or error message
20+
"""
21+
try:
22+
# Create a simple script that recreates the AI logic without interactive input
23+
script_content = f'''
24+
import sys
25+
import os
26+
27+
# Add project paths
28+
project_root = "{os.path.dirname(os.path.dirname(__file__))}"
29+
sys.path.insert(0, project_root)
30+
31+
# Import required modules
32+
from db.db_helpers import get_db_session
33+
from db.models import DpdHeadword
34+
from tools.paths import ProjectPaths
35+
from tools.paths_dps import DPSPaths
36+
from tools.ai_related import (
37+
load_translation_examples,
38+
replace_abbreviations,
39+
handle_ai_response,
40+
get_ai_client,
41+
generate_messages_for_meaning,
42+
generate_messages_for_notes
43+
)
44+
45+
# Initialize paths and database
46+
pth = ProjectPaths()
47+
dpspth = DPSPaths()
48+
db_session = get_db_session(pth.dpd_db_path)
49+
50+
# Recreate the working function logic
51+
def fetch_id(db_session, id_to_check):
52+
if not id_to_check:
53+
return None
54+
query = db_session.query(DpdHeadword).filter(DpdHeadword.id == id_to_check).first()
55+
return query
56+
57+
# Get headword data
58+
pali_word = fetch_id(db_session, {headword_id})
59+
if pali_word:
60+
lemma_1 = pali_word.lemma_1
61+
meaning = pali_word.meaning_1
62+
pos = pali_word.pos
63+
grammar = pali_word.grammar
64+
sentence = pali_word.example_1
65+
notes = pali_word.notes
66+
67+
# Load translation examples and prepare grammar
68+
pos_example_map = load_translation_examples(dpspth)
69+
translation_example = pos_example_map.get(pos, "")
70+
71+
if "{provider}" == "openai":
72+
# model = "gpt-4.1-mini"
73+
model = "gpt-4.1"
74+
elif "{provider}" == "deepseek":
75+
model = "deepseek-chat"
76+
grammar_orig = grammar
77+
grammar = replace_abbreviations(grammar)
78+
79+
# Generate appropriate messages
80+
if "{mode}" == "meaning":
81+
messages = generate_messages_for_meaning(lemma_1, grammar, meaning, sentence, translation_example, {synonyms})
82+
elif "{mode}" == "note":
83+
messages = generate_messages_for_notes(lemma_1, grammar, notes)
84+
85+
# Get AI client and handle response
86+
client = get_ai_client("{provider}")
87+
suggestion, error_string = handle_ai_response(client, messages, model, "{provider}")
88+
89+
if error_string:
90+
print(f"AI Error: {{error_string}}")
91+
elif suggestion:
92+
suggestion_str = suggestion.get("content", "") if suggestion is not None else ""
93+
print(suggestion_str)
94+
else:
95+
print("No response from AI")
96+
else:
97+
print(f"Error: Headword {{headword_id}} not found in database")
98+
'''
99+
100+
# Run the script as subprocess
101+
result = subprocess.run(
102+
[sys.executable, "-c", script_content],
103+
capture_output=True,
104+
text=True,
105+
timeout=120, # 2 minute timeout
106+
cwd=os.path.dirname(os.path.dirname(__file__)) # Run from project root
107+
)
108+
109+
# Debug: Print full output for troubleshooting
110+
print(f"DEBUG - Subprocess return code: {result.returncode}")
111+
print(f"DEBUG - Subprocess stdout: {result.stdout}")
112+
print(f"DEBUG - Subprocess stderr: {result.stderr}")
113+
114+
if result.returncode == 0:
115+
# Success - return the output
116+
return result.stdout.strip()
117+
else:
118+
# Error - return both stdout and stderr for debugging
119+
return f"AI Error (return code {result.returncode}): stdout='{result.stdout.strip()}', stderr='{result.stderr.strip()}'"
120+
121+
except subprocess.TimeoutExpired:
122+
return "AI Error: Timeout - AI processing took too long"
123+
except Exception as e:
124+
return f"Subprocess Error: {str(e)}"

gui2/dps_ai_service.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env python3
2+
"""AI service for DPS GUI - uses subprocess to avoid signal errors"""
3+
4+
from gui2.dps_ai_cli_wrapper import run_ai_via_subprocess
5+
6+
# Default AI provider
7+
DEFAULT_PROVIDER = "openai"
8+
9+
10+
def translate_with_ai_from_gui(dps_fields, mode: str, synonyms: bool = False, provider: str = DEFAULT_PROVIDER):
11+
"""
12+
Uses subprocess to run AI translation in separate process to avoid signal conflicts.
13+
14+
Args:
15+
dps_fields: DpsFields instance containing GUI field values
16+
mode: "meaning" or "note"
17+
provider: AI provider ("openai" or "deepseek")
18+
synonyms: Whether to generate synonyms (for meaning mode)
19+
20+
Returns:
21+
AI-generated suggestion or error message
22+
"""
23+
try:
24+
# Get headword ID from GUI field
25+
headword_id_field = dps_fields.fields.get("dps_dpd_id")
26+
if not headword_id_field or not headword_id_field.value:
27+
return "Error: No headword ID found in GUI"
28+
29+
try:
30+
headword_id = int(headword_id_field.value)
31+
except ValueError:
32+
return f"Error: Invalid headword ID: {headword_id_field.value}"
33+
34+
# Use subprocess to run AI in separate process (avoids signal errors)
35+
result = run_ai_via_subprocess(headword_id, mode, synonyms, provider)
36+
37+
# Check if result contains error
38+
if "Error:" in result or "Timeout" in result:
39+
return result
40+
else:
41+
# Success - return the AI-generated suggestion
42+
return result
43+
44+
except Exception as e:
45+
return f"Error in AI service: {str(e)}"

0 commit comments

Comments
 (0)