Repository: sharingan-no-kakashi/orange-intelligence
Branch: main
Commit: 02e7d3ff8e80
Files: 29
Total size: 45.9 KB
Directory structure:
gitextract_roayer6_/
├── .flake8
├── .gitignore
├── Contributing.md
├── README.md
├── app.py
├── config.py
├── core/
│ ├── __init__.py
│ ├── controller.py
│ ├── model.py
│ └── views/
│ ├── __init__.py
│ ├── floating_window.py
│ ├── styling/
│ │ ├── __init__.py
│ │ └── floating_window_style.py
│ ├── system_tray.py
│ └── text_processing.py
├── extensions/
│ ├── __init__.py
│ ├── basics/
│ │ └── __init__.py
│ ├── langraph/
│ │ ├── __init__.py
│ │ └── langraph.py
│ ├── ollama/
│ │ ├── __init__.py
│ │ └── example.py
│ ├── openai/
│ │ ├── __init__.py
│ │ └── utils.py
│ └── variables.py
├── makefile
├── pyproject.toml
├── tests/
│ ├── __init__.py
│ └── test_dummy.py
└── utils/
└── __init__.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .flake8
================================================
[flake8]
max-line-length = 120
exclude =
.git,
__pycache__,
.venv,
build,
dist,
# ANN101: Missing type annotation for self in method
# ANN102: Missing type annotation for cls in method
# D400: First line should end with a period for a docstring
# D401: First line should be in imperative mood for a docstring
# ANN003: Missing type annotation for a kwargs argument
extend-ignore=ANN101,ANN102,D400,D401,ANN003,N802
suppress-none-returning=true
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
.vscode/
.python-version
================================================
FILE: Contributing.md
================================================
# Contributing to Orange Intelligence
We’re thrilled that you want to contribute to Orange Intelligence! While we don’t have a fully established contribution process at the moment, here’s what it should look like:
---
## 🛠 Contribution Workflow
1. **Open an Issue**
- Start by opening an issue in this repository.
- Use a proper tag to classify your issue:
- `ux`: For UI/UX improvements.
- `bug`: For bugs or unexpected behavior.
- `feature-request`: For new features you'd like to see.
- `extension-function`: For proposing new functions/extensions to be added to the floating window.
- Wait for feedback before diving into implementation. We don’t want you to waste valuable time on something that might not align with the project’s goals.
2. **Create a Pull Request (PR)**
- Once your issue is approved, fork the repository and start working on your changes.
- When ready, submit a PR linked to your issue.
3. **Make the CI Happy**
- Ensure your code passes all linting and tests. Run these locally before pushing your changes.
4. **Celebrate Your Contribution!**
- Once your PR is merged, enjoy the satisfaction of contributing to an open-source project. 🎉
---
## 🧹 Code Style
We strive to maintain clean, consistent, and readable code. Please follow these practices:
- Run linters (`black`, `flake8`) before submitting your PR.
- Include unit tests for new features or fixes where applicable.
---
## 📝 Notes
- If you have ideas but aren’t sure how to implement them, feel free to open an issue just to discuss!
- Don’t hesitate to ask questions if you’re stuck—collaboration is key.
---
Thank you for helping make Orange Intelligence better! 🧡
================================================
FILE: README.md
================================================
# 🍊 Orange Intelligence
**A Better Open Source Version of Apple Intelligence for macOS**
Orange Intelligence is a powerful, fully customizable productivity tool for macOS. With its elegant floating window interface, you can capture, process, and replace text seamlessly across any application. Whether you're running basic text processing, leveraging the power of large language models (LLMs) like OpenAI or local LLaMA, or creating complex agent systems, Orange Intelligence empowers you to work smarter, faster, and better.
---
## 🌟 Why Orange Intelligence?
Apple Intelligence is closed, limited, and inflexible. Orange Intelligence brings the power of customization and open source innovation to macOS, making it the perfect productivity tool for developers, researchers, and AI enthusiasts.
---
## Demo
| Feature | Demo GIF |
|----------------------------------|-------------------------------|
| **Variables and text processing examples** |  |
| **LLMs with local Ollama** |  |
## ✨ Features
- **Floating Text Processor**: Double-tap the `Option` key to open a sleek floating window.
- **Run Any Python Function**: Execute any Python code, from simple string manipulations to advanced AI/LLM integrations (OpenAI, local LLaMA, or your own agents).
- **Fully Customizable**: Add your own Python logic to extend its functionality and tailor the app to your specific workflows.
- **Global variable replacement**: Global variable replacement (You no longer need to open your notes app to do a simple copy and paste!)
---
## 🛠️ How It Works
Orange Intelligence simplifies text processing with a three-step pipeline:
1. **Capture Text from Any Application**
- Using a clever Applescript trick, the app simulates a global `Cmd+C` to grab the content of the clipboard from the active application.
2. **Process the Text**
- The floating window opens in focus, allowing the user to select which Python function to run. The selected function processes the clipboard text (e.g., formatting, AI generation, etc.).
3. **Replace the Text**
- Once processed, the floating window closes, the focus returns to the previous app, and a global `Cmd+V` pastes the updated content back into the app.
---
## 🚀 Getting Started
### Prerequisites
1. **Install Python 3.9+**
2. **Install Poetry** for dependency management:
```bash
pip install poetry
```
3. **Grant Permissions**: Ensure your Python interpreter has the following rights:
- **Accessibility**: To allow replacing text via `Cmd+V`.
- **Input Monitoring**: To listen for global key shortcuts like the `Option` key.
4. **Optional Dependencies**:
- **Ollama**: If you want to run local LLaMA models, ensure [Ollama](https://ollama.ai/) is installed and running.
- If you have a custom setup, you might need to adapt the Python code for your environment.
5. **Optional Configuration**:
- Adjust the log level in `config.py` if needed.
### Installation
1. Clone this repository:
```bash
git clone [https://github.com/sharingan-no-kakashi/orange-intelligence.git]
cd orange-intelligence
```
2. Install dependencies using Poetry:
```bash
poetry install
```
3. Start the app using Make:
```bash
make run
```
(Use `make help` to see other available commands.)
4. When the **orange icon** appears in the system tray, the app is ready to use.
### Usage
1. Highlight any text in a macOS application.
2. Double-tap the `Option` key to bring up the floating window.
3. Select a function to apply to the highlighted text.
---
## 🧩 Customization
- Add custom logic by defining callable Python objects in the `extensions` package.
- **Every function (or callable object)** defined in the `__init__.py` file of the `extensions` package will automatically appear as an option in the floating window.
Example:
```python
# extensions/__init__.py
def reverse_text(input_text):
return input_text[::-1]
```
---
## 📝 To-Do and Future Improvements
These are the features currently in progress:
- **Custom Prompts**: Add the ability to pass custom prompts (hint: that's why you see `**kwargs` in the code).
- **Text Playground**: Open a new custom window for text processing, allowing users to combine LLM/Python/text utilities in a single workspace.
- **Clipboard Restoration**: Automatically restore the content of the clipboard after processing operations.
- **UI/UX Enhancements**: Improve the design and user experience for better usability.
- **Code improvements**: The codebase feels a bit hacky at the moment, there are lots debatable decisions (subprocessing/time.sleep(), controller feels a bit overwhelmed of logic) etc
- **Other platforms support** There is probably no reason why this cannot be extended to other platforms linux/window.
- **CI/CD** Setup a nice ci pipeline to run the lint/banding/mypy and handling versions/releases
---
## 🏗️ Tech Stack
- **Python**: The core logic of the app is written in Python for flexibility and extensibility.
- **PyQt6**: Provides a polished and responsive UI for the floating window, built with a clean MVC architecture.
- **Applescript**: Facilitates system-level clipboard interactions and application switching.
---
## 📝 License
This project is licensed under the [MIT License](LICENSE).
---
## 🤝 Contributing
We welcome contributions! Check out the [CONTRIBUTING.md](Contributing.md) for guidelines on how to get involved.
---
## 📧 Contact
Questions, feedback, or ideas? Reach out via Github issues.
---
**Empower your workflow with 🍊 Orange Intelligence — because better is open source.**
================================================
FILE: app.py
================================================
import logging.config
import sys
from config import CONFIG
from PyQt6.QtWidgets import QApplication
from utils import avoid_dock_macos_icon
from core.controller import Controller
from core.model import Model
def main():
logging.config.dictConfig(CONFIG["logging"])
app = QApplication(sys.argv)
avoid_dock_macos_icon()
model = Model()
controller = Controller(model=model, view=app)
# Run the event loop
sys.exit(controller.view.exec())
if __name__ == "__main__":
main()
================================================
FILE: config.py
================================================
import os
import sys
import tempfile
LOGGING_LEVEL = "DEBUG"
CONFIG = {
"app": {
"name": "orange-ai",
"icon": "assets/icon.png",
},
"variables": {
"import_bash_profile": False,
},
"ollama": {
"name": "ollama",
"url": "https://ollama.com",
"default_model": "llama3.1",
},
"openai": {"api_key": os.environ.get("OPENAPI_KEY"), "default_model": "gpt-3.5-turbo"},
"logging": {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"detailed": {"format": "%(asctime)s - %(levelname)s - %(name)s - %(message)s"},
},
"handlers": {
"stream": {
"level": LOGGING_LEVEL,
"class": "logging.StreamHandler",
"stream": sys.stdout,
"formatter": "detailed",
},
"file": {
"level": LOGGING_LEVEL,
"class": "logging.FileHandler",
"filename": tempfile.NamedTemporaryFile(delete=False).name,
"formatter": "detailed",
},
},
"loggers": {
"": { # Root logger configuration
"handlers": ["stream", "file"],
"level": LOGGING_LEVEL,
"propagate": True,
},
},
},
}
================================================
FILE: core/__init__.py
================================================
================================================
FILE: core/controller.py
================================================
import logging
import time
import pyperclip
from pynput import keyboard
from PyQt6.QtCore import QTimer, pyqtSignal
from PyQt6.QtWidgets import QApplication
from utils import cmd_v, get_current_process_id, get_focused_text, put_app_in_focus, return_app_in_focus
from core.model import Model
from core.views.floating_window import FloatingWindow
from core.views.system_tray import SystemTray
from core.views.text_processing import TextWindow
LOG = logging.getLogger(__name__)
class Controller:
def __init__(self, model: Model, view: QApplication):
self.view = view
self.model = model
self.option_key = False
self.last_time = 0.0
self.floating_window_open = False
self.text_window_open = False
self.focused_process_id = ""
self.focused_text = ""
self.processed_text = ""
self.cmd_pressed = False
self.option_pressed = False
self.this_process_id = get_current_process_id()
self.setup_windows()
self.listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
self.listener.start()
def get_window_tabs_items(self) -> dict[str, list[str]]:
return self.model.sections
def update_floating_window_status(self, statue: bool):
self.floating_window_open = statue
def update_text_window_status(self, status: bool):
self.text_window_open = status
def setup_event_handlers(self):
self.view.floating_window.custom_signal.connect(self.process_text)
self.view.floating_window.event_put_app_focus.connect(self.put_this_app_in_focus)
self.view.text_window.event_put_app_focus.connect(self.put_this_app_in_focus)
self.view.floating_window.windows_event.connect(self.update_floating_window_status)
self.view.text_window.windows_event.connect(self.update_text_window_status)
def recreate_text_window(self):
LOG.debug("Recreating text window")
self.view.text_window = TextWindow(
processing_text=self.focused_text, functions_list=self.model.get_all_functions_flattened()
)
LOG.debug("Text window recreated")
def setup_windows(self) -> None:
self.view.main_window = SystemTray()
# Create the system tray icon
self.view.main_window.show()
# Create the floating window, passing the key listener to it
tabs = self.get_window_tabs_items()
self.view.floating_window = FloatingWindow(tabs)
self.recreate_text_window()
self.setup_event_handlers()
def get_focused_text(self) -> None:
self.focused_text = get_focused_text()
def return_app_in_focus(self) -> None:
self.focused_process_id = return_app_in_focus()
def put_previous_app_in_focus(self) -> None:
return put_app_in_focus(self.focused_process_id)
def put_this_app_in_focus(self) -> None:
return put_app_in_focus(self.this_process_id)
def set_processed_text(self, section: str, item: str, **kwargs) -> str:
processed_text = self.model.process_text(section, item, self.focused_text, **{})
pyperclip.copy(processed_text)
self.put_previous_app_in_focus()
time.sleep(0.3)
cmd_v()
return self.processed_text
def process_text(self, section: str, item: str) -> None:
QTimer.singleShot(0, lambda: self.set_processed_text(section, item))
def on_press(self, key: keyboard.Key) -> None:
try:
# Detect if the pressed key is Cmd or Option (Alt)
if key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
self.option_pressed = True
elif key == keyboard.Key.cmd_l or key == keyboard.Key.cmd_r:
self.cmd_pressed = True
# If both Cmd and Option keys are pressed simultaneously, open another window
if self.cmd_pressed and self.option_pressed:
if not self.text_window_open:
self.open_text_window()
self.text_window_open = True
self.cmd_pressed = False # Reset after action to avoid repeated detection
self.option_pressed = False
# If only the Option key is pressed, follow the original logic
elif self.option_pressed:
current_time = time.time()
# If two presses are detected within 1 second, open the window
if current_time - self.last_time < 0.8:
if self.floating_window_open:
self.close_floating_window()
else:
self.open_floating_window()
self.last_time = current_time
self.option_pressed = False # Reset after action
except AttributeError as e:
LOG.debug(f"AttributeError: {e}")
pass
def _open_text_window(self) -> None:
LOG.debug("Opening text window")
self.recreate_text_window()
def open_text_window(self) -> None:
pass # This is still unreliable
def open_floating_window(self) -> None:
self.get_focused_text()
self.return_app_in_focus()
QTimer.singleShot(0, self.view.floating_window.show)
self.floating_window_open = True
def close_floating_window(self) -> None:
QTimer.singleShot(0, self.view.floating_window.close)
self.put_previous_app_in_focus()
self.floating_window_open = False
def on_release(self, key: keyboard.Key) -> None:
# Reset flags when keys are released
if key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
self.option_pressed = False
elif key == keyboard.Key.cmd_l or key == keyboard.Key.cmd_r:
self.cmd_pressed = False
================================================
FILE: core/model.py
================================================
import logging
from utils import load_all_available_functions
import extensions
import extensions.ollama.example
from extensions.variables import variables
LOG = logging.getLogger(__name__)
from functools import reduce
class Model:
def __init__(self):
self.functions = load_all_available_functions(extensions)
self.sections = self.get_sections()
self.variables = variables
def get_all_functions_flattened(self) -> dict[str, str]:
return reduce(lambda x, y: {**x, **y}, self.functions.values(), {})
def get_sections(self) -> dict[str, list[str]]:
sections = {section: list(functions.keys()) for section, functions in self.functions.items()}
sections["variables"] = list(variables.keys())
return sections
def process_text(self, section: str, function_name: str, input_text: str, **kwargs) -> str:
if section == "variables":
return self.variables[function_name]
return self.functions[section][function_name](input_text, **kwargs)
================================================
FILE: core/views/__init__.py
================================================
================================================
FILE: core/views/floating_window.py
================================================
import logging
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QCloseEvent, QHideEvent, QKeyEvent, QShowEvent
from PyQt6.QtWidgets import QListWidget, QListWidgetItem, QTabWidget, QVBoxLayout, QWidget
from core.views.styling.floating_window_style import FloatingWindowStyleOptions
LOG = logging.getLogger(__name__)
class FloatingWindow(QWidget):
custom_signal = pyqtSignal(str, str)
windows_event = pyqtSignal(bool)
process_text_event = pyqtSignal(str, str, str)
event_put_app_focus = pyqtSignal()
def __init__(self, tab_sections: dict):
super().__init__()
# Set macOS-style window appearance
self.setWindowTitle(FloatingWindowStyleOptions.title)
self.setGeometry(200, 200, 400, 300)
self.setStyleSheet(FloatingWindowStyleOptions.base)
self.tab_widget = QTabWidget()
self.tab_scroll_positions = {}
self.set_up_tab_widget(tab_sections)
def keyPressEvent(self, event: QKeyEvent) -> None:
current_index = self.tab_widget.currentIndex()
current_widget = self.tab_widget.currentWidget()
if event.key() == Qt.Key.Key_Escape:
self.close()
# Retrieve the QListWidget inside the current tab
if current_widget:
list_widget = current_widget.findChild(QListWidget)
if list_widget and isinstance(list_widget, QListWidget):
# If the current tab contains a QListWidget
if event.key() == Qt.Key.Key_Up:
current_row = list_widget.currentRow()
new_row = max(0, current_row - 1)
list_widget.setCurrentRow(new_row)
elif event.key() == Qt.Key.Key_Down:
current_row = list_widget.currentRow()
new_row = min(list_widget.count() - 1, current_row + 1)
list_widget.setCurrentRow(new_row)
if event.key() == Qt.Key.Key_Return:
# Handle Enter key
current_item = list_widget.currentItem() # Get the currently selected item
if current_item:
tab_name = self.tab_widget.tabText(current_index)
row_text = current_item.text()
self.handle_enter_key(tab_name, row_text, current_index)
else:
LOG.debug("No item selected in the current list.")
else:
LOG.debug("Current tab does not contain a QListWidget.")
else:
LOG.debug("No current widget in the tab.")
# Handle Left and Right arrow keys to switch tabs
if event.key() == Qt.Key.Key_Right:
next_index = (current_index + 1) % self.tab_widget.count()
self.tab_widget.setCurrentIndex(next_index)
elif event.key() == Qt.Key.Key_Left:
previous_index = (current_index - 1) % self.tab_widget.count()
self.tab_widget.setCurrentIndex(previous_index)
else:
# Pass other key events to the parent class
super().keyPressEvent(event)
def set_up_tab_widget(self, tab_sections: dict) -> None:
# Create the tab widget
self.tab_widget.setTabsClosable(False)
self.tab_widget.setStyleSheet(FloatingWindowStyleOptions.tab_widget)
# Create tabs
self.create_tabs(tab_sections)
# Main layout
main_layout = QVBoxLayout()
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.addWidget(self.tab_widget)
self.setLayout(main_layout)
# Initialize scroll positions for all tabs
for i in range(self.tab_widget.count()):
self.tab_scroll_positions[i] = 0
def create_tabs(self, tab_sections: dict) -> None:
for section_name, tab_section in tab_sections.items():
tab = QWidget()
tab_layout = QVBoxLayout()
list_widget = QListWidget()
list_widget.setStyleSheet(FloatingWindowStyleOptions.list_widget)
tab_layout.addWidget(list_widget)
for key in tab_section:
item = QListWidgetItem(key)
list_widget.addItem(item)
list_widget.setCurrentRow(0) # Set the current row to the first item
tab.setLayout(tab_layout) # Set layout for the tab
self.tab_widget.addTab(tab, section_name) # Add the tab
def handle_enter_key(self, tab_name: str, text_item: str, tab_index: int) -> None:
"""Close the window and trigger the processText function."""
self.custom_signal.emit(tab_name, text_item)
self.close() # Close the window
def closeEvent(self, event: QCloseEvent) -> None:
# Hide the window instead of closing it to prevent application shutdown
event.ignore()
self.hide()
# Update the key listener state when the window is hidden
self.windows_event.emit(False)
def hideEvent(self, event: QHideEvent) -> None:
# Ensure the key listener flag is updated when the window is hidden
self.windows_event.emit(False)
def showEvent(self, event: QShowEvent) -> None:
super().showEvent(event)
# Ensure the window is focused when shown
self.raise_() # Raise the window to the top
self.activateWindow() # Make the window active (focused)
self.windows_event.emit(True)
self.event_put_app_focus.emit()
================================================
FILE: core/views/styling/__init__.py
================================================
================================================
FILE: core/views/styling/floating_window_style.py
================================================
class FloatingWindowStyleOptions:
geometry = "200, 200, 400, 300"
title = "Orange GUI"
base = """
QWidget {
background-color: #f4f4f4;
border: 1px solid #ccc;
border-radius: 10px;
padding: 0;
}
"""
tab_widget = """
QTabWidget::pane {
border: none;
background: transparent;
}
QTabBar::tab {
background: #f8f8f8;
border: none;
padding: 8px 16px;
margin: 2px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
QTabBar::tab:selected {
background: #ffffff;
font-weight: bold;
color: #007aff;
}
QTabBar::tab:hover {
background: #e9e9e9;
}
"""
search_bar = """
QLineEdit {
background-color: #ffffff;
border: 1px solid #d1d1d1;
border-radius: 6px;
padding: 6px;
margin: 6px 0;
}
"""
list_widget = """
QListWidget {
background-color: #ffffff;
border: 1px solid #d1d1d1;
border-radius: 6px;
margin: 8px;
}
QListWidget::item {
padding: 8px;
font-size: 14px;
color: #333;
}
QListWidget::item:selected {
background-color: #007aff;
color: #ffffff;
font-weight: bold;
border-radius: 4px;
margin: 2px;
}
QListWidget::item:hover {
background-color: #e0e0e0;
color: #000;
}
"""
================================================
FILE: core/views/system_tray.py
================================================
from config import CONFIG
from PyQt6.QtCore import QCoreApplication
from PyQt6.QtGui import QAction, QIcon
from PyQt6.QtWidgets import QMenu, QSystemTrayIcon
class SystemTray(QSystemTrayIcon):
def __init__(self):
icon = CONFIG.get("app").get("icon")
super().__init__(QIcon(icon))
# Create the tray menu
self.menu = QMenu()
# Add actions to the menu
self.create_menu_actions()
# Set the menu to the tray icon
self.setContextMenu(self.menu)
def create_menu_actions(self):
"""Creates and adds actions to the context menu."""
# Action to quit the application
quit_action = QAction("❌ Quit", self)
quit_action.triggered.connect(self.quit_app)
quit_action.setToolTip("Quit the application")
# Add actions to the menu
self.menu.addAction(quit_action)
def open_settings(self):
"""Placeholder for a settings dialog."""
self.show_message("Settings", "Settings window would appear here.")
def show_message(self, title: str, message: str):
"""Displays a message balloon from the system tray."""
self.showMessage(title, message, QSystemTrayIcon.MessageIcon.Information)
def quit_app(self):
"""Exits the application."""
QCoreApplication.quit()
================================================
FILE: core/views/text_processing.py
================================================
import logging
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QCloseEvent, QHideEvent, QShowEvent
from PyQt6.QtWidgets import (
QAbstractItemView,
QFrame,
QHBoxLayout,
QLineEdit,
QListWidget,
QPushButton,
QSplitter,
QTabWidget,
QTextEdit,
QVBoxLayout,
QWidget,
)
LOG = logging.getLogger(__name__)
class TextWindow(QWidget):
custom_signal = pyqtSignal(str, str)
windows_event = pyqtSignal(bool)
process_text_event = pyqtSignal(str, str, str)
event_put_app_focus = pyqtSignal()
def __init__(self, processing_text, functions_list):
super().__init__()
LOG.debug(f"Creating text window processing text, {processing_text}")
# Layout for the main window
main_layout = QHBoxLayout(self)
self.processing_text = processing_text
# Create QTabWidget for text areas
self.text_tab_widget = QTabWidget()
self.functions_list = functions_list
# Add initial text tab
self.text_tab = QWidget()
text_layout = QVBoxLayout(self.text_tab)
self.text_widget = QTextEdit()
self.text_widget.setText(self.processing_text)
text_layout.addWidget(self.text_widget)
self.text_tab_widget.addTab(self.text_tab, "Text 1")
# Create QTabWidget for functions list
self.function_tab_widget = QTabWidget()
# Tab 1 - Function list
self.function_list_tab = QWidget()
function_layout = QVBoxLayout(self.function_list_tab)
self.function_list_widget = QListWidget()
function_layout.addWidget(self.function_list_widget)
self.function_tab_widget.addTab(self.function_list_tab, "Functions 1")
# Add function names to the list
for function_name in functions_list:
self.function_list_widget.addItem(function_name)
# Set the function list widget to be selectable
self.function_list_widget.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
# Tab 2 - Text area for functions
self.function_text_tab = QWidget()
function_text_layout = QVBoxLayout(self.function_text_tab)
function_text_widget = QTextEdit()
function_text_layout.addWidget(function_text_widget)
self.function_tab_widget.addTab(self.function_text_tab, "Function Text")
# Split the main layout into two sections: one for text and one for functions
splitter = QSplitter(Qt.Orientation.Horizontal)
splitter.addWidget(self.text_tab_widget)
splitter.addWidget(self.function_tab_widget)
# Set stretch factors to ensure text and function sections take 90% of the space
splitter.setStretchFactor(0, 9) # Text section takes 9 parts
splitter.setStretchFactor(1, 9) # Function section takes 9 parts
# Add splitter to the main layout
main_layout.addWidget(splitter)
# Bottom input area with 3 text inputs and buttons, occupying 10% of the horizontal space
bottom_layout = QVBoxLayout()
# Create a container frame for the bottom section to control its width
bottom_frame = QFrame()
bottom_frame.setLayout(bottom_layout)
# Create 3 text input fields and 3 run buttons, and add them vertically
self.inputs = [QLineEdit() for _ in range(3)]
self.run_buttons = [QPushButton("Run") for _ in range(3)]
for input_field, button in zip(self.inputs, self.run_buttons):
bottom_layout.addWidget(input_field)
bottom_layout.addWidget(button)
# Add the bottom frame to the main layout, occupying 10% of the horizontal space
bottom_frame.setFixedWidth(self.width() // 10) # Set the width to 10% of the window size
main_layout.addWidget(bottom_frame)
self.setLayout(main_layout)
self.setWindowTitle("Text Display and Function List")
self.resize(800, 600)
# Connect context menus for adding new tabs
self.text_tab_widget.tabBar().setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.text_tab_widget.tabBar().customContextMenuRequested.connect(self.showTextTabMenu)
self.function_tab_widget.tabBar().setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.function_tab_widget.tabBar().customContextMenuRequested.connect(self.showFunctionTabMenu)
# Connect the Enter key event to the function application
self.function_list_widget.keyPressEvent = self.handle_function_key_event
def handle_function_key_event(self, event):
if event.key() == Qt.Key.Key_Return: # Detect Enter key press
# Get the selected function name from the list
selected_item = self.function_list_widget.currentItem()
if selected_item:
function_name = selected_item.text()
# Apply the function to the displayed text
self.apply_function(function_name)
else:
super().keyPressEvent(event) # Pass the event to the base class if it's not Enter
def apply_function(self, function_name):
# Check if the function name exists in the functions list
if function_name in self.functions_list:
# Apply the function to the current text in the text widget
func = self.functions_list[function_name]
new_text = func(self.text_widget.toPlainText())
self.text_widget.setText(new_text) # Update the text widget with the result
def showTextTabMenu(self, pos):
# Create and show context menu for adding new text tabs
menu = self.text_tab_widget.tabBar().createStandardContextMenu()
add_tab_action = menu.addAction("Add New Text Tab")
add_tab_action.triggered.connect(self.add_new_text_tab)
menu.exec(self.text_tab_widget.tabBar().mapToGlobal(pos))
def showFunctionTabMenu(self, pos):
# Create and show context menu for adding new function tabs
menu = self.function_tab_widget.tabBar().createStandardContextMenu()
add_tab_action = menu.addAction("Add New Function Tab")
add_tab_action.triggered.connect(self.add_new_function_tab)
menu.exec(self.function_tab_widget.tabBar().mapToGlobal(pos))
def add_new_text_tab(self):
# Create new text tab
new_text_tab = QWidget()
new_text_layout = QVBoxLayout(new_text_tab)
new_text_widget = QTextEdit()
new_text_layout.addWidget(new_text_widget)
# Add the new text tab
new_tab_index = self.text_tab_widget.addTab(new_text_tab, f"Text {self.text_tab_widget.count() + 1}")
# Optionally set the new tab as the current tab
self.text_tab_widget.setCurrentIndex(new_tab_index)
def add_new_function_tab(self):
# Create new function list tab
new_function_list_tab = QWidget()
new_function_list_layout = QVBoxLayout(new_function_list_tab)
new_function_list_widget = QListWidget()
new_function_list_widget.addItem("Uppercase") # Default function item
new_function_list_widget.addItem("Lowercase")
new_function_list_layout.addWidget(new_function_list_widget)
# Add the new function list tab
new_function_list_tab_index = self.function_tab_widget.addTab(
new_function_list_tab, f"Functions {self.function_tab_widget.count() + 1}"
)
# Create new function text tab
new_function_text_tab = QWidget()
new_function_text_layout = QVBoxLayout(new_function_text_tab)
new_function_text_widget = QTextEdit()
new_function_text_layout.addWidget(new_function_text_widget)
# Add the new function text tab
new_function_text_tab_index = self.function_tab_widget.addTab(
new_function_text_tab, f"Function Text {self.function_tab_widget.count()}"
)
# Optionally set the new function list tab as the current tab
self.function_tab_widget.setCurrentIndex(new_function_list_tab_index)
def closeEvent(self, event: QCloseEvent) -> None:
# Hide the window instead of closing it to prevent application shutdown
event.ignore()
self.hide()
# Update the key listener state when the window is hidden
self.windows_event.emit(False)
def hideEvent(self, event: QHideEvent) -> None:
# Ensure the key listener flag is updated when the window is hidden
self.windows_event.emit(False)
def showEvent(self, event: QShowEvent) -> None:
LOG.debug("Text window shown")
super().showEvent(event)
# Ensure the window is focused when shown
self.raise_() # Raise the window to the top
self.activateWindow() # Make the window active (focused)
self.windows_event.emit(True)
self.event_put_app_focus.emit()
================================================
FILE: extensions/__init__.py
================================================
================================================
FILE: extensions/basics/__init__.py
================================================
import json
def upper_case(text: str, **kwargs) -> str:
return text.upper()
def lower_case(text: str, **kwargs) -> str:
return text.lower()
def pretty_json(text: str, **kwargs) -> str:
return json.dumps(json.loads(text), indent=4)
def a_complex_task_you_do_not_want_to_implement_now(text: str, **kwargs) -> str:
return "This is a complex task that you do not want to implement now."
================================================
FILE: extensions/langraph/__init__.py
================================================
================================================
FILE: extensions/langraph/langraph.py
================================================
================================================
FILE: extensions/ollama/__init__.py
================================================
from extensions.ollama.example import improve_grammar, make_it_polite, translate_to_english # noqa: F401
================================================
FILE: extensions/ollama/example.py
================================================
import logging
from config import CONFIG
from ollama import ChatResponse, chat
LOG = logging.getLogger(__name__)
def ollama(prompt: str) -> str:
response: ChatResponse = chat(
model=CONFIG["ollama"]["default_model"],
messages=[
{
"role": "user",
"content": prompt,
},
],
)
# or access fields directly from the response object
LOG.debug(response.message.content)
return response.message.content
def improve_grammar(input_text: str, **kwargs) -> str:
prompt = (
"Improve the grammar of this sentence. Return only the improved sentence, do not add anything else. "
+ input_text
)
return ollama(prompt)
def translate_to_english(input_text: str, **kwargs) -> str:
prompt = (
"Translate this sentence to English. Return only the translated sentence, do not add anything else. "
+ input_text
)
return ollama(prompt)
def make_it_polite(input_text: str, **kwargs) -> str:
prompt = (
"Convert this sentence to a polite one. Return only the converted sentence, do not add anything else. "
+ input_text
)
return ollama(prompt)
================================================
FILE: extensions/openai/__init__.py
================================================
from extensions.openai.utils import _chat_completion_endpoint
def make_a_joke(text: str, **kwargs) -> str:
prompt = f"Tell me a joke about {text}"
return _chat_completion_endpoint(prompt)
================================================
FILE: extensions/openai/utils.py
================================================
from config import CONFIG
from openai import OpenAI
def _chat_completion_endpoint(content: str) -> str:
client = OpenAI(api_key=CONFIG["openai"]["api_key"])
chat_completion = client.chat.completions.create(
messages=[
{
"role": "user",
"content": content,
}
],
model=CONFIG["openai"]["default_model"],
)
return chat_completion.choices[0].message.content
================================================
FILE: extensions/variables.py
================================================
import os
dev_db_user = os.environ.get("dev_db_user") or "user"
variables = {
"my name:": "Yoda",
"thing i always forget": "42",
"s3 bucket with a weird name": "prod-thing-i-always-forget",
"Prd kafka endpoint": "https://prod-thing-i-always-forget.s3.amazonaws.com",
"that thing once told me": "John Snow knows nothing",
"Json config dev": '{"s3bucket":"dev-bucket", "db": {"user": "%s"} }' % dev_db_user,
}
================================================
FILE: makefile
================================================
PROJECT ?= orange-intelligence
VERSION ?= $(shell grep -m 1 version pyproject.toml | tr -s ' ' | tr -d '"' | tr -d "'" | cut -d' ' -f3)
PYTHON_VERSION = $(shell grep 'python =' pyproject.toml | sed -n 's/^python = ["^]*\([0-9]*\.[0-9]*\)\(.*\)"/\1/p')
version: ## Show the current version
echo "Current version: $(VERSION)"
help: ## Show help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort |\
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-16s\033[0m %s\n", $$1, $$2}'
.DEFAULT_GOAL=help
.python-version: ## Installs the correct version of python if required
$(if $(shell pyenv versions --bare | grep "^$(PYTHON_VERSION)"),, pyenv install $(PYTHON_VERSION))
pyenv local $(shell pyenv versions --bare | grep "^$(PYTHON_VERSION)" | tail -n 1)
.venv: .python-version ## Activates and installs the poetry environment.
poetry env use ~/.pyenv/versions/$(shell cat $<)/bin/python && \
poetry install
lint: .venv ## Lint the project
poetry run flake8
mypy: .venv ## Run mypy
poetry run mypy
test: .venv ## Test the project
poetry run pytest
fmt: .venv ## Run formatting tools for project
poetry run black . $(if $(CI),--check ,) && poetry run isort . $(if $(CI),--check ,)
bandit: .venv ## Run bandit
poetry run bandit -c pyproject.toml -r .
check: fmt lint mypy bandit test ; ## Run all checks
run:
poetry run python3 app.py
clean: ## Clean the project
rm -rf .venv
rm -rf .python-version
rm -rf dist/
rm -rf __pycache__
rm -rf .pytest_cache
rm -rf .mypy_cache
================================================
FILE: pyproject.toml
================================================
[tool.poetry]
name = "orange-intelligence"
version = "0.1.0"
description = "The Orange Intelligence for mac os x"
authors = ["Pietro"]
readme = "README.md"
packages = [
{ include = "core" },
{ include = "extensions" },
]
[tool.poetry.dependencies]
python = "^3.9"
pynput = "1.7.7"
pyperclip="1.9.0"
PyQt6="6.8.0"
ollama="0.4.7"
pyobjc-framework-Cocoa="11.0"
openai="1.60.1"
[tool.poetry.dev-dependencies]
black = "^23.7.0"
flake8 = "^6.1.0"
isort = "^5.12.0"
mypy = "^1.8.0"
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
flake8-eradicate = "^1.5.0"
flake8-pytest-style = "^1.7.2"
pep8-naming = "^0.13.3"
flake8-bugbear = "^24.2.6"
flake8-annotations = "^3.0.1"
flake8-simplify = "^0.21.0"
flake8-print = "^5.0.0"
bandit = {extras = ["toml"], version = "^1.7.7"}
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.black]
line-length = 120
target-version = ['py312']
include = '\.pyi?$'
exclude = '''
^/(
(
\.eggs
| .venv
| \.git
| build
| dist
| notebooks
)
)
'''
[tool.isort]
line_length = 120
profile = "black"
src_paths = ["core", "tests", "extensions"]
[tool.pytest.ini_options]
minversion = "6.0"
testpaths = ["tests"]
python_files = ["tests.py", "test_*.py", "*_tests.py"]
[tool.coverage.report]
exclude_also = [
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
]
[tool.mypy]
files = ["core/**/*.py", "extensions/**/*.py", "tests/**/*.py", "utils/**/*.py"]
follow_imports = "normal"
strict_optional = "False"
warn_redundant_casts = "True"
warn_unused_ignores = "True"
disallow_any_generics = "False"
check_untyped_defs = "True"
no_implicit_reexport = "True"
no_implicit_optional = "True"
disallow_untyped_defs = "False"
ignore_missing_imports = "True"
namespace_packages = "True"
disallow_any_unimported = "True"
exclude = []
[tool.bandit]
exclude_dirs = ["tests", ".venv", "dist"]
================================================
FILE: tests/__init__.py
================================================
================================================
FILE: tests/test_dummy.py
================================================
def test_dummy_assert_true():
assert True
================================================
FILE: utils/__init__.py
================================================
import importlib
import logging
import os
import pkgutil
import subprocess
import sys
import time
import types
import typing
import pyperclip
from AppKit import NSApp
from PyQt6.QtCore import QProcess
LOG = logging.getLogger(__name__)
def get_current_process_id() -> str:
return f"{os.getpid()}"
def get_focused_text() -> str:
cmd_c()
time.sleep(0.3)
# Get clipboard content
clipboard_content = pyperclip.paste()
return clipboard_content.strip()
def cmd_v() -> None:
applescript = """
tell application "System Events"
keystroke "v" using {command down}
end tell
"""
subprocess.run(["osascript", "-e", applescript])
def return_app_in_focus() -> str:
command = """/usr/bin/osascript -e 'tell application "System Events"
set frontApp to first application process whose frontmost is true
return unix id of frontApp
end tell' """
res = subprocess.run(command, shell=True, stdin=sys.stdin, stdout=subprocess.PIPE, stderr=sys.stderr, text=True)
return res.stdout.strip()
def cmd_c() -> None:
applescript = """
tell application "System Events"
keystroke "c" using {command down}
end tell
"""
subprocess.run(["osascript", "-e", applescript])
def put_app_in_focus(process_id: str) -> None:
script = f"""tell application "System Events"
set frontmost of (first process whose unix id is {process_id}) to true
end tell"""
QProcess.startDetached("/usr/bin/osascript", ["-e", script])
def put_this_app_in_focus() -> None:
this_process_id = get_current_process_id()
return put_app_in_focus(this_process_id)
def import_package_init_functions(package: types.ModuleType) -> dict[str, dict[str, typing.Callable]]:
# List all submodules (modules and subpackages) in the package
submodules = [module.name for module in pkgutil.iter_modules(package.__path__)]
callables = {}
for submodule in submodules:
# Dynamically import the __init__.py of the subpackage
try:
subpackage = importlib.import_module(f"{package.__name__}.{submodule}")
if hasattr(subpackage, "__init__"):
# Get all callables (functions and callable objects) in the __init__.py of the subpackage
subpackage_callables = {
item: getattr(subpackage, item)
for item in dir(subpackage)
if callable(getattr(subpackage, item))
if not item.startswith("_")
}
# Store callables with their names
callables[submodule] = subpackage_callables
except Exception as e:
LOG.error(f"Error importing {submodule}: {e}")
return callables
def load_all_available_functions(package: types.ModuleType) -> dict[str, dict[str, typing.Callable]]:
return {name: functions for name, functions in import_package_init_functions(package).items() if len(functions) > 0}
def avoid_dock_macos_icon():
NSApp.setActivationPolicy_(1)
gitextract_roayer6_/
├── .flake8
├── .gitignore
├── Contributing.md
├── README.md
├── app.py
├── config.py
├── core/
│ ├── __init__.py
│ ├── controller.py
│ ├── model.py
│ └── views/
│ ├── __init__.py
│ ├── floating_window.py
│ ├── styling/
│ │ ├── __init__.py
│ │ └── floating_window_style.py
│ ├── system_tray.py
│ └── text_processing.py
├── extensions/
│ ├── __init__.py
│ ├── basics/
│ │ └── __init__.py
│ ├── langraph/
│ │ ├── __init__.py
│ │ └── langraph.py
│ ├── ollama/
│ │ ├── __init__.py
│ │ └── example.py
│ ├── openai/
│ │ ├── __init__.py
│ │ └── utils.py
│ └── variables.py
├── makefile
├── pyproject.toml
├── tests/
│ ├── __init__.py
│ └── test_dummy.py
└── utils/
└── __init__.py
SYMBOL INDEX (74 symbols across 13 files)
FILE: app.py
function main (line 12) | def main():
FILE: core/controller.py
class Controller (line 18) | class Controller:
method __init__ (line 19) | def __init__(self, model: Model, view: QApplication):
method get_window_tabs_items (line 36) | def get_window_tabs_items(self) -> dict[str, list[str]]:
method update_floating_window_status (line 39) | def update_floating_window_status(self, statue: bool):
method update_text_window_status (line 42) | def update_text_window_status(self, status: bool):
method setup_event_handlers (line 45) | def setup_event_handlers(self):
method recreate_text_window (line 53) | def recreate_text_window(self):
method setup_windows (line 60) | def setup_windows(self) -> None:
method get_focused_text (line 73) | def get_focused_text(self) -> None:
method return_app_in_focus (line 76) | def return_app_in_focus(self) -> None:
method put_previous_app_in_focus (line 79) | def put_previous_app_in_focus(self) -> None:
method put_this_app_in_focus (line 82) | def put_this_app_in_focus(self) -> None:
method set_processed_text (line 85) | def set_processed_text(self, section: str, item: str, **kwargs) -> str:
method process_text (line 93) | def process_text(self, section: str, item: str) -> None:
method on_press (line 96) | def on_press(self, key: keyboard.Key) -> None:
method _open_text_window (line 129) | def _open_text_window(self) -> None:
method open_text_window (line 133) | def open_text_window(self) -> None:
method open_floating_window (line 136) | def open_floating_window(self) -> None:
method close_floating_window (line 142) | def close_floating_window(self) -> None:
method on_release (line 147) | def on_release(self, key: keyboard.Key) -> None:
FILE: core/model.py
class Model (line 14) | class Model:
method __init__ (line 15) | def __init__(self):
method get_all_functions_flattened (line 20) | def get_all_functions_flattened(self) -> dict[str, str]:
method get_sections (line 23) | def get_sections(self) -> dict[str, list[str]]:
method process_text (line 29) | def process_text(self, section: str, function_name: str, input_text: s...
FILE: core/views/floating_window.py
class FloatingWindow (line 12) | class FloatingWindow(QWidget):
method __init__ (line 18) | def __init__(self, tab_sections: dict):
method keyPressEvent (line 29) | def keyPressEvent(self, event: QKeyEvent) -> None:
method set_up_tab_widget (line 76) | def set_up_tab_widget(self, tab_sections: dict) -> None:
method create_tabs (line 94) | def create_tabs(self, tab_sections: dict) -> None:
method handle_enter_key (line 111) | def handle_enter_key(self, tab_name: str, text_item: str, tab_index: i...
method closeEvent (line 116) | def closeEvent(self, event: QCloseEvent) -> None:
method hideEvent (line 123) | def hideEvent(self, event: QHideEvent) -> None:
method showEvent (line 127) | def showEvent(self, event: QShowEvent) -> None:
FILE: core/views/styling/floating_window_style.py
class FloatingWindowStyleOptions (line 1) | class FloatingWindowStyleOptions:
FILE: core/views/system_tray.py
class SystemTray (line 7) | class SystemTray(QSystemTrayIcon):
method __init__ (line 8) | def __init__(self):
method create_menu_actions (line 22) | def create_menu_actions(self):
method open_settings (line 33) | def open_settings(self):
method show_message (line 37) | def show_message(self, title: str, message: str):
method quit_app (line 41) | def quit_app(self):
FILE: core/views/text_processing.py
class TextWindow (line 22) | class TextWindow(QWidget):
method __init__ (line 28) | def __init__(self, processing_text, functions_list):
method handle_function_key_event (line 116) | def handle_function_key_event(self, event):
method apply_function (line 127) | def apply_function(self, function_name):
method showTextTabMenu (line 136) | def showTextTabMenu(self, pos):
method showFunctionTabMenu (line 143) | def showFunctionTabMenu(self, pos):
method add_new_text_tab (line 150) | def add_new_text_tab(self):
method add_new_function_tab (line 163) | def add_new_function_tab(self):
method closeEvent (line 191) | def closeEvent(self, event: QCloseEvent) -> None:
method hideEvent (line 198) | def hideEvent(self, event: QHideEvent) -> None:
method showEvent (line 202) | def showEvent(self, event: QShowEvent) -> None:
FILE: extensions/basics/__init__.py
function upper_case (line 4) | def upper_case(text: str, **kwargs) -> str:
function lower_case (line 8) | def lower_case(text: str, **kwargs) -> str:
function pretty_json (line 12) | def pretty_json(text: str, **kwargs) -> str:
function a_complex_task_you_do_not_want_to_implement_now (line 16) | def a_complex_task_you_do_not_want_to_implement_now(text: str, **kwargs)...
FILE: extensions/ollama/example.py
function ollama (line 10) | def ollama(prompt: str) -> str:
function improve_grammar (line 25) | def improve_grammar(input_text: str, **kwargs) -> str:
function translate_to_english (line 33) | def translate_to_english(input_text: str, **kwargs) -> str:
function make_it_polite (line 41) | def make_it_polite(input_text: str, **kwargs) -> str:
FILE: extensions/openai/__init__.py
function make_a_joke (line 4) | def make_a_joke(text: str, **kwargs) -> str:
FILE: extensions/openai/utils.py
function _chat_completion_endpoint (line 6) | def _chat_completion_endpoint(content: str) -> str:
FILE: tests/test_dummy.py
function test_dummy_assert_true (line 1) | def test_dummy_assert_true():
FILE: utils/__init__.py
function get_current_process_id (line 18) | def get_current_process_id() -> str:
function get_focused_text (line 22) | def get_focused_text() -> str:
function cmd_v (line 30) | def cmd_v() -> None:
function return_app_in_focus (line 39) | def return_app_in_focus() -> str:
function cmd_c (line 48) | def cmd_c() -> None:
function put_app_in_focus (line 57) | def put_app_in_focus(process_id: str) -> None:
function put_this_app_in_focus (line 64) | def put_this_app_in_focus() -> None:
function import_package_init_functions (line 69) | def import_package_init_functions(package: types.ModuleType) -> dict[str...
function load_all_available_functions (line 96) | def load_all_available_functions(package: types.ModuleType) -> dict[str,...
function avoid_dock_macos_icon (line 100) | def avoid_dock_macos_icon():
Condensed preview — 29 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (50K chars).
[
{
"path": ".flake8",
"chars": 465,
"preview": "[flake8]\nmax-line-length = 120\nexclude =\n .git,\n __pycache__,\n .venv,\n build,\n dist,\n\n# ANN101: Missing t"
},
{
"path": ".gitignore",
"chars": 3468,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "Contributing.md",
"chars": 1759,
"preview": "# Contributing to Orange Intelligence \n\nWe’re thrilled that you want to contribute to Orange Intelligence! While we don"
},
{
"path": "README.md",
"chars": 5819,
"preview": "# 🍊 Orange Intelligence \n\n**A Better Open Source Version of Apple Intelligence for macOS** \n\nOrange Intelligence is a "
},
{
"path": "app.py",
"chars": 512,
"preview": "import logging.config\nimport sys\n\nfrom config import CONFIG\nfrom PyQt6.QtWidgets import QApplication\nfrom utils import a"
},
{
"path": "config.py",
"chars": 1355,
"preview": "import os\nimport sys\nimport tempfile\n\nLOGGING_LEVEL = \"DEBUG\"\n\nCONFIG = {\n \"app\": {\n \"name\": \"orange-ai\",\n "
},
{
"path": "core/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "core/controller.py",
"chars": 5808,
"preview": "import logging\nimport time\n\nimport pyperclip\nfrom pynput import keyboard\nfrom PyQt6.QtCore import QTimer, pyqtSignal\nfro"
},
{
"path": "core/model.py",
"chars": 1038,
"preview": "import logging\n\nfrom utils import load_all_available_functions\n\nimport extensions\nimport extensions.ollama.example\nfrom "
},
{
"path": "core/views/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "core/views/floating_window.py",
"chars": 5485,
"preview": "import logging\n\nfrom PyQt6.QtCore import Qt, pyqtSignal\nfrom PyQt6.QtGui import QCloseEvent, QHideEvent, QKeyEvent, QSho"
},
{
"path": "core/views/styling/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "core/views/styling/floating_window_style.py",
"chars": 1737,
"preview": "class FloatingWindowStyleOptions:\n geometry = \"200, 200, 400, 300\"\n\n title = \"Orange GUI\"\n\n base = \"\"\"\n "
},
{
"path": "core/views/system_tray.py",
"chars": 1330,
"preview": "from config import CONFIG\nfrom PyQt6.QtCore import QCoreApplication\nfrom PyQt6.QtGui import QAction, QIcon\nfrom PyQt6.Qt"
},
{
"path": "core/views/text_processing.py",
"chars": 8881,
"preview": "import logging\n\nfrom PyQt6.QtCore import Qt, pyqtSignal\nfrom PyQt6.QtGui import QCloseEvent, QHideEvent, QShowEvent\nfrom"
},
{
"path": "extensions/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "extensions/basics/__init__.py",
"chars": 407,
"preview": "import json\n\n\ndef upper_case(text: str, **kwargs) -> str:\n return text.upper()\n\n\ndef lower_case(text: str, **kwargs) "
},
{
"path": "extensions/langraph/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "extensions/langraph/langraph.py",
"chars": 0,
"preview": ""
},
{
"path": "extensions/ollama/__init__.py",
"chars": 106,
"preview": "from extensions.ollama.example import improve_grammar, make_it_polite, translate_to_english # noqa: F401\n"
},
{
"path": "extensions/ollama/example.py",
"chars": 1210,
"preview": "import logging\n\nfrom config import CONFIG\n\nfrom ollama import ChatResponse, chat\n\nLOG = logging.getLogger(__name__)\n\n\nde"
},
{
"path": "extensions/openai/__init__.py",
"chars": 199,
"preview": "from extensions.openai.utils import _chat_completion_endpoint\n\n\ndef make_a_joke(text: str, **kwargs) -> str:\n prompt "
},
{
"path": "extensions/openai/utils.py",
"chars": 455,
"preview": "from config import CONFIG\n\nfrom openai import OpenAI\n\n\ndef _chat_completion_endpoint(content: str) -> str:\n client = "
},
{
"path": "extensions/variables.py",
"chars": 434,
"preview": "import os\n\ndev_db_user = os.environ.get(\"dev_db_user\") or \"user\"\n\nvariables = {\n \"my name:\": \"Yoda\",\n \"thing i alw"
},
{
"path": "makefile",
"chars": 1501,
"preview": "PROJECT ?= orange-intelligence\nVERSION ?= $(shell grep -m 1 version pyproject.toml | tr -s ' ' | tr -d '\"' | tr -d \"'\" |"
},
{
"path": "pyproject.toml",
"chars": 1880,
"preview": "[tool.poetry]\nname = \"orange-intelligence\"\nversion = \"0.1.0\"\ndescription = \"The Orange Intelligence for mac os x\"\nauthor"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/test_dummy.py",
"chars": 46,
"preview": "def test_dummy_assert_true():\n assert True\n"
},
{
"path": "utils/__init__.py",
"chars": 3101,
"preview": "import importlib\nimport logging\nimport os\nimport pkgutil\nimport subprocess\nimport sys\nimport time\nimport types\nimport ty"
}
]
About this extraction
This page contains the full source code of the sharingan-no-kakashi/orange-intelligence GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 29 files (45.9 KB), approximately 11.6k tokens, and a symbol index with 74 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.