Minor bug fixes
This commit is contained in:
21
README.md
21
README.md
@@ -101,24 +101,10 @@ Download platform-specific binaries:
|
|||||||
# Extract and install
|
# Extract and install
|
||||||
unzip oai_vx.x.x_mac_arm64.zip # or `oai_vx.x.x-linux-x86_64.zip`
|
unzip oai_vx.x.x_mac_arm64.zip # or `oai_vx.x.x-linux-x86_64.zip`
|
||||||
chmod +x oai
|
chmod +x oai
|
||||||
mkdir -p ~/.local/bin
|
mkdir -p ~/.local/bin # Remember to add this to your path. Or just move to folder already in your $PATH
|
||||||
mv oai ~/.local/bin/
|
mv oai ~/.local/bin/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Option 3: Build Your Own Binary
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install build dependencies
|
|
||||||
pip install -r requirements.txt
|
|
||||||
pip install nuitka ordered-set zstandard
|
|
||||||
|
|
||||||
# Run build script
|
|
||||||
chmod +x build.sh
|
|
||||||
./build.sh
|
|
||||||
|
|
||||||
# Binary will be in dist/oai
|
|
||||||
cp dist/oai ~/.local/bin/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Alternative: Shell Alias
|
### Alternative: Shell Alias
|
||||||
|
|
||||||
@@ -508,6 +494,7 @@ Full license: https://opensource.org/licenses/MIT
|
|||||||
|
|
||||||
**Rune Olsen**
|
**Rune Olsen**
|
||||||
|
|
||||||
|
- Homepage: https://ai.fubar.pm/
|
||||||
- Blog: https://blog.rune.pm
|
- Blog: https://blog.rune.pm
|
||||||
- Project: https://iurl.no/oai
|
- Project: https://iurl.no/oai
|
||||||
|
|
||||||
@@ -527,3 +514,7 @@ Contributions welcome! Please:
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Star ⭐ this project if you find it useful!**
|
**Star ⭐ this project if you find it useful!**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Did you really read all the way down here? WOW! You deserve a 🍾 🥂!
|
||||||
|
|||||||
63
oai.py
63
oai.py
@@ -4650,25 +4650,55 @@ def chat():
|
|||||||
file_attachments = []
|
file_attachments = []
|
||||||
content_blocks = []
|
content_blocks = []
|
||||||
|
|
||||||
# Smart file detection with extension whitelist
|
# Smart file detection: Simple pattern + extension validation
|
||||||
# Only matches files with known extensions or clear path prefixes
|
# This avoids extremely long regex that can cause binary signing issues
|
||||||
#
|
|
||||||
# Valid matches:
|
|
||||||
# @/path/to/file
|
|
||||||
# @~/file.txt
|
|
||||||
# @./script.py
|
|
||||||
# @report.pdf
|
|
||||||
#
|
|
||||||
# Excludes:
|
|
||||||
# @domain.com (no whitelisted extension)
|
|
||||||
# @mail.server.eu (TLD not in whitelist)
|
|
||||||
# user@domain.com (email pattern)
|
|
||||||
# Diagnostic-Code: @server.eu (TLD not in whitelist)
|
|
||||||
|
|
||||||
file_pattern = r'(?:^|\s)@((?:[~/][\S]+)|(?:\.[\S]+)|(?:[\w][\w-]*\.(?:py|txt|md|log|json|csv|pdf|png|jpg|jpeg|gif|bmp|webp|svg|ico|zip|tar|gz|bz2|7z|rar|xz|js|ts|jsx|tsx|vue|html|css|scss|sass|less|xml|yaml|yml|toml|ini|conf|cfg|env|properties|sh|bash|zsh|fish|bat|cmd|ps1|c|cpp|cc|cxx|h|hpp|hxx|java|class|jar|war|rb|go|rs|swift|kt|kts|php|sql|db|sqlite|sqlite3|lock|gitignore|dockerignore|editorconfig|eslintrc|prettierrc|babelrc|nvmrc|npmrc|pyc|pyo|pyd|so|dll|dylib|exe|app|dmg|pkg|deb|rpm|apk|ipa|wasm|proto|graphql|graphqls|grpc|avro|parquet|orc|feather|arrow|hdf5|h5|mat|r|rdata|rds|pkl|pickle|joblib|npy|npz|safetensors|onnx|pt|pth|ckpt|pb|tflite|mlmodel|coreml|rknn)))(?=\s|$)'
|
# Common file extensions we support
|
||||||
|
ALLOWED_FILE_EXTENSIONS = {
|
||||||
|
# Code
|
||||||
|
'.py', '.js', '.ts', '.jsx', '.tsx', '.vue', '.java', '.c', '.cpp', '.cc', '.cxx',
|
||||||
|
'.h', '.hpp', '.hxx', '.rb', '.go', '.rs', '.swift', '.kt', '.kts', '.php',
|
||||||
|
'.sh', '.bash', '.zsh', '.fish', '.bat', '.cmd', '.ps1',
|
||||||
|
# Data
|
||||||
|
'.json', '.csv', '.yaml', '.yml', '.toml', '.xml', '.sql', '.db', '.sqlite', '.sqlite3',
|
||||||
|
# Documents
|
||||||
|
'.txt', '.md', '.log', '.conf', '.cfg', '.ini', '.env', '.properties',
|
||||||
|
# Images
|
||||||
|
'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.svg', '.ico',
|
||||||
|
# Archives
|
||||||
|
'.zip', '.tar', '.gz', '.bz2', '.7z', '.rar', '.xz',
|
||||||
|
# Config files
|
||||||
|
'.lock', '.gitignore', '.dockerignore', '.editorconfig', '.eslintrc',
|
||||||
|
'.prettierrc', '.babelrc', '.nvmrc', '.npmrc',
|
||||||
|
# Binary/Compiled
|
||||||
|
'.pyc', '.pyo', '.pyd', '.so', '.dll', '.dylib', '.exe', '.app',
|
||||||
|
'.dmg', '.pkg', '.deb', '.rpm', '.apk', '.ipa',
|
||||||
|
# ML/AI
|
||||||
|
'.pkl', '.pickle', '.joblib', '.npy', '.npz', '.safetensors', '.onnx',
|
||||||
|
'.pt', '.pth', '.ckpt', '.pb', '.tflite', '.mlmodel', '.coreml', '.rknn',
|
||||||
|
# Data formats
|
||||||
|
'.wasm', '.proto', '.graphql', '.graphqls', '.grpc', '.avro', '.parquet',
|
||||||
|
'.orc', '.feather', '.arrow', '.hdf5', '.h5', '.mat', '.r', '.rdata', '.rds',
|
||||||
|
# Other
|
||||||
|
'.pdf', '.class', '.jar', '.war'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Simple pattern: @filepath where filepath starts with ~, /, . or has an extension
|
||||||
|
# Much shorter than listing all extensions in the regex
|
||||||
|
file_pattern = r'(?:^|\s)@([~/\.][\S]+|[\w][\w-]*\.[\w]+)(?=\s|$)'
|
||||||
|
|
||||||
for match in re.finditer(file_pattern, user_input, re.IGNORECASE):
|
for match in re.finditer(file_pattern, user_input, re.IGNORECASE):
|
||||||
file_path = match.group(1)
|
file_path = match.group(1)
|
||||||
|
|
||||||
|
# Get the extension
|
||||||
|
file_ext = os.path.splitext(file_path)[1].lower()
|
||||||
|
|
||||||
|
# Skip if it doesn't start with a path char and has no allowed extension
|
||||||
|
if not file_path.startswith(('/', '~', '.', '\\')):
|
||||||
|
if not file_ext or file_ext not in ALLOWED_FILE_EXTENSIONS:
|
||||||
|
# This looks like a domain name, not a file
|
||||||
|
continue
|
||||||
|
|
||||||
expanded_path = os.path.expanduser(os.path.abspath(file_path))
|
expanded_path = os.path.expanduser(os.path.abspath(file_path))
|
||||||
|
|
||||||
if not os.path.exists(expanded_path) or os.path.isdir(expanded_path):
|
if not os.path.exists(expanded_path) or os.path.isdir(expanded_path):
|
||||||
@@ -4681,7 +4711,6 @@ def chat():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
mime_type, _ = mimetypes.guess_type(expanded_path)
|
mime_type, _ = mimetypes.guess_type(expanded_path)
|
||||||
file_ext = os.path.splitext(expanded_path)[1].lower()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(expanded_path, 'rb') as f:
|
with open(expanded_path, 'rb') as f:
|
||||||
@@ -4729,7 +4758,7 @@ def chat():
|
|||||||
app_logger.error(f"File read error for {expanded_path}: {e}")
|
app_logger.error(f"File read error for {expanded_path}: {e}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Remove file attachments from text (use same pattern as file detection)
|
# Remove file attachments from text (use same simple pattern)
|
||||||
text_part = re.sub(file_pattern, lambda m: m.group(0)[0] if m.group(0)[0].isspace() else '', text_part).strip()
|
text_part = re.sub(file_pattern, lambda m: m.group(0)[0] if m.group(0)[0].isspace() else '', text_part).strip()
|
||||||
|
|
||||||
# Build message content
|
# Build message content
|
||||||
|
|||||||
Reference in New Issue
Block a user