Skip to content
Merged
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
34 changes: 34 additions & 0 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Python CI

on:
push:
branches: [main, "**"]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: [3.11]

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest

- name: Run tests
run: |
pytest -v
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,32 @@ Example:
coaia tash my_key --f path/to/value/file.txt
```

#### Fetch Value from Redis

To fetch a value from Redis by key:

```bash
coaia fetch <key>
```

Example:

```bash
coaia fetch my_key
```

To fetch a value from Redis and save it to a file:

```bash
coaia fetch <key> --output <file_path>
```

Example:

```bash
coaia fetch my_key --output path/to/output/file.txt
```

#### Process Custom Tags

Enable custom quick addons for assistants or bots using process tags. To add a new process tag to `coaia.json`, include entries like:
Expand All @@ -129,4 +155,3 @@ Contributions are welcome! Please open an issue or submit a pull request for any
## License

This project is licensed under the MIT License. See the LICENSE file for more details.

9 changes: 8 additions & 1 deletion coaiapy/coaiacli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))

from coaiamodule import read_config, transcribe_audio, summarizer, tash, abstract_process_send, initial_setup
from coaiamodule import read_config, transcribe_audio, summarizer, tash, abstract_process_send, initial_setup, fetch_key_val
from cofuse import (
get_comments, post_comment,
create_session_and_save, add_trace_node_and_save,
Expand Down Expand Up @@ -157,6 +157,11 @@ def main():
parser_ds_items_create.add_argument('-e','--expected', help="Expected output")
parser_ds_items_create.add_argument('-m','--metadata', help="Optional metadata as JSON string")

# Subparser for 'fetch' command
parser_fetch = subparsers.add_parser('fetch', help='Fetch a value from Redis by key.')
parser_fetch.add_argument('key', type=str, help="The key to fetch.")
parser_fetch.add_argument('-O', '--output', type=str, help="Filename to save the fetched value.")

args = parser.parse_args()

if args.command == 'init':
Expand Down Expand Up @@ -210,6 +215,8 @@ def main():
f.write(summary)
else:
print(f"{summary}")
elif args.command == 'fetch':
fetch_key_val(args.key, args.output)
elif args.command == 'fuse':
if args.fuse_command == 'comments':
if args.action == 'list':
Expand Down
29 changes: 27 additions & 2 deletions coaiapy/coaiamodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def remove_placeholder_lines(text):
# Split the text into lines
lines = text.split('\n')
# Iterate over the lines and remove lines starting with "Placeholder"
cleaned_lines = [line for line in lines if not line.startswith("Placeholder")]
cleaned_lines = [line for line for line in lines if not line.startswith("Placeholder")]

# Join the cleaned lines back into a string
cleaned_text = '\n'.join(cleaned_lines)
Expand Down Expand Up @@ -261,7 +261,7 @@ def d2s_send(input_message, temperature=None,pre=''):

temperature = config['d2s_default_temperature'] if temperature is None else temperature

system_instruction = config.get('d2s_instruction', 'You do : Receive a text that requires to put details into shapes. you keep the essence of what is discussed foreach elements you observe and able yo group in the inout text.')
system_instruction = config.get('d2s_instruction', 'You do : Receive a text that requires to put details into shapes. you group elements of different nature and summarize them. REMEMBER: Dont introduce nor conclude, just output results. No comments.')


# Concatenate preprompt_instruction with input_message
Expand Down Expand Up @@ -604,6 +604,31 @@ def tash(k:str,v:str,ttl=None,quiet=False):
print('Stashing failed')
return result

def fetch_key_val(key, output_file=None):
try:
jtalecnf = read_config()['jtaleconf']
_r = _newjtaler(jtalecnf)
if _r is None:
print("Error: Redis connection failed.")
sys.exit(2)
value = _r.get(key)
if value is None:
print(f"Error: Key '{key}' not found in Redis memory.")
sys.exit(1)
value = value.decode('utf-8')
if output_file:
with open(output_file, 'w') as file:
file.write(value)
print(f"Key: {key} fetched and saved to {output_file}")
else:
print(value)
except redis.ConnectionError:
print("Error: Redis connection failed.")
sys.exit(2)
except Exception as e:
print(f"Error: {str(e)}")
sys.exit(1)

def initial_setup():
sample_config = {
"username": "SSH_USER",
Expand Down
51 changes: 51 additions & 0 deletions coaiapy/test_cli_fetch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest
from unittest.mock import patch, MagicMock
import sys
import os
import io
import redis
from coaiapy.coaiacli import fetch_key_val

# Mock Redis fixture
@pytest.fixture
def mock_redis(monkeypatch):
mock_redis_instance = MagicMock()
monkeypatch.setattr('redis.Redis', lambda *args, **kwargs: mock_redis_instance)
return mock_redis_instance

# Mock broken Redis fixture
@pytest.fixture
def mock_broken_redis(monkeypatch):
mock_redis_instance = MagicMock()
mock_redis_instance.get.side_effect = redis.ConnectionError
monkeypatch.setattr('redis.Redis', lambda *args, **kwargs: mock_redis_instance)
return mock_redis_instance

def test_fetch_stdout_key_found(mock_redis):
mock_redis.get.return_value = b'This is a memory snippet.'
with patch('sys.stdout', new_callable=io.StringIO) as mock_stdout, \
patch('coaiapy.coaiamodule._newjtaler') as mock_newjtaler:
mock_newjtaler.return_value = mock_redis
fetch_key_val('mykey')
assert mock_stdout.getvalue().strip() == 'This is a memory snippet.'

def test_fetch_output_file_key_found(mock_redis):
mock_redis.get.return_value = b'This is a memory snippet.'
output_file = 'memory.txt'
fetch_key_val('mykey', output_file)
with open(output_file, 'r') as file:
assert file.read().strip() == 'This is a memory snippet.'
os.remove(output_file)

def test_fetch_key_not_found_exits_1(mock_redis):
mock_redis.get.return_value = None
with pytest.raises(SystemExit) as pytest_wrapped_e:
fetch_key_val('mykey')
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1

def test_fetch_redis_down_exits_2(mock_broken_redis):
with pytest.raises(SystemExit) as pytest_wrapped_e:
fetch_key_val('mykey')
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 2
Loading