Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ src/dataset/agent-v1-c4/datasets.json
.DS_Store
src/.DS_Store
.env
tests/*
tests/*
uv.lock
callgraph.json
lancedbsrc1/lancedb_src*
FiniteMonkey*/*
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12.9
22 changes: 22 additions & 0 deletions .vscode/code-explorer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"#": "NOT recommend to edit manually. Write carefully! Generated by tianjianchn.code-explorer vscode extension.",
"#markerCount": 1,
"stacks": [
{
"title": "class root(BaseM 2025-02-14",
"isActive": true,
"createdAt": "2025-02-15T00:17:34.074Z",
"id": "98d72628b1bb5d4b6be2bb35a6f73501",
"markers": [
{
"code": "class root(BaseModel):",
"file": "src/root.py",
"line": 3,
"column": 0,
"createdAt": "2025-02-15T00:17:53.463Z",
"id": "156f801ac1de21e620e787f199161418"
}
]
}
]
}
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File with Arguments",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
},
{
"name": "Python Debugger: Python File",
"type": "debugpy",
"request": "launch",
"program": "${file}"
}
]
}
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
174 changes: 174 additions & 0 deletions app/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
from textual import work
from textual.app import App
from textual.widgets import Footer, Header
from models.schemas import LogCtxData
from ui.widgets import ThinSpinner, BilingualTable, TranslationToggle
import asyncio
from textual.containers import VerticalScroll, Horizontal
from textual.widgets import Input
import asyncio
import sys
import io
from textual import app, work
from textual.widgets import Input, RichLog
from textual.widgets import ProgressBar
from textual.reactive import reactive
#from rich.layout import VerticalScroll
from textual.app import ComposeResult
from textual.containers import Vertical, VerticalScroll, Horizontal


from textual.containers import Container, Horizontal, Vertical
from textual.widgets import DataTable, Switch, Static
from textual import work, on
from textual.reactive import var
from app.translation import TranslationService


class CoreApp(App):
CSS = """
#main-content {
layout: grid;
grid-size: 2;
grid-columns: 1fr 1fr;
height: 1fr;
}
"""
translation_enabled = var(True) # Enabled by default

async def on_mount(self):
self.main_loop = asyncio.get_running_loop()
self.start_ipython()

@work(thread=True, exclusive=True)
def start_ipython(self):
"""Start IPython in background thread"""
import sys
from IPython import start_ipython

class IPythonWrapper:
def __init__(self, app):
self.app = app

def write(self, data):
asyncio.run_coroutine_threadsafe(
self.app.post_output(data),
loop=self.app.main_loop
)
def flush(self):
pass

def isatty(self):
return False # Crucial fix for prompt_toolkit integration

def fileno(self):
return -1 # Indicate no real file descriptor


sys.stdout = IPythonWrapper(self)
start_ipython(argv=[], user_ns={
"app": self,
"toggle_translation": self.toggle_translation
})

async def post_output(self, data: str):
"""Handle output from IPython thread"""
if self.translation_enabled:
# Add translation logic here
self.query_one(BilingualTable).add_row(data)
else:
self.query_one(BilingualTable).add_row(data)
self.refresh()

def action_quit(self):
self.exit()

def toggle_translation(self, enabled: bool):
"""Toggle translation mode from IPython"""
self.translation_enabled = enabled
self.notify(f"Translation {'enabled' if enabled else 'disabled'}")

CSS = """
#main-content {
layout: grid;
grid-size: 2;
grid-columns: 1fr 1fr;
height: 1fr;
}
"""
translation_enabled = var(True) # Enabled by default

def compose(self):
# Top controls
yield Horizontal(
ThinSpinner(),
TranslationToggle(value=True), # Toggle enabled by default
id="spinner-container"
)

# Main content - side by side tables
yield Horizontal(
BilingualTable("English", lang="EN"),
BilingualTable("中文", lang="CN"),
id="main-content"
)

# Input at bottom
yield Horizontal(
Input(placeholder="Input text/commands >>> "),
id="input-container"
)

async def process_output(self, data: str):
"""Process all output with bidirectional translation"""
try:
# Detect input language
is_english = self._is_english(data)
source_lang = "EN" if is_english else "CN"
target_lang = "CN" if is_english else "EN"

# Create translation context
ctx = LogCtxData(
txtENG=data if is_english else "",
txtCN=data if not is_english else "",
detail="Auto-translation"
)

# Always show original + translation when enabled
if self.translation_enabled:
translated = await self.translation.translate(ctx, target_lang)
self._update_tables(
source_text=data,
translated_text=translated,
source_lang=source_lang
)
else:
self._update_single_table(data, source_lang)

except Exception as e:
self.log_error(f"Translation error: {str(e)}")

def _update_tables(self, source_text: str, translated_text: str, source_lang: str):
"""Update both tables with original and translation"""
en_table = self.query_one("#english-table")
zh_table = self.query_one("#chinese-table")

if source_lang == "EN":
en_table.add_row(source_text)
zh_table.add_row(translated_text)
else:
zh_table.add_row(source_text)
en_table.add_row(translated_text)

def _update_single_table(self, text: str, source_lang: str):
"""Update only the relevant table when translation off"""
table = self.query_one("#english-table" if source_lang == "EN" else "#chinese-table")
table.add_row(text)

@on(Input.Submitted)
async def handle_input(self, event: Input.Submitted):
"""Handle user input with immediate translation"""
input_text = event.value
if input_text:
await self.process_output(input_text)
event.input.clear()
Loading