Skip to content
This repository was archived by the owner on Apr 23, 2025. It is now read-only.
2 changes: 1 addition & 1 deletion .cursor/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"memory": {
"command": "npx -y @modelcontextprotocol/server-memory",
"env": {
"MEMORY_PATH": ".cursor/memory.json"
"MEMORY_PATH": "scripts/memorystore.json"
}
},
"Atlassian MCP": {
Expand Down
10 changes: 10 additions & 0 deletions scripts/ghauth.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
# ghauth.sh - GitHub CLI wrapper to use the correct authentication token
# Usage: source scripts/ghauth.sh
# ghauth <any-gh-command>

ghauth() {
GITHUB_TOKEN="" gh "$@"
}

echo "GitHub CLI auth wrapper loaded. Use 'ghauth' instead of 'gh' for commands requiring full repo access."
53 changes: 53 additions & 0 deletions scripts/memory.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash
# memory.sh - Backup and restore assistant memory
# Usage:
# ./scripts/memory.sh backup - Creates a backup of assistant memory
# ./scripts/memory.sh restore - Provides instructions to restore memory

BACKUP_FILE="scripts/memory_backup.json"

function backup_memory() {
echo "To create a memory backup:"
echo "1. Ask the assistant: 'Please create a memory backup'"
echo "2. The assistant will use mcp_memory_read_graph tool to read current memory"
echo "3. The assistant will update $BACKUP_FILE with current memory contents"
echo
echo "You can also ask the assistant to add specific information to memory before backing up."
}

function restore_memory() {
if [ ! -f "$BACKUP_FILE" ]; then
echo "Backup file not found: $BACKUP_FILE"
exit 1
fi

echo "This script will help you restore memory in a new assistant session."
echo "Instructions:"
echo "1. When starting a new chat with the assistant, paste the following instructions:"
echo
echo "------- COPY BELOW THIS LINE -------"
echo "Please restore my memory backup from the scripts/memory_backup.json file"
echo "Steps:"
echo "1. Read the file content with read_file tool"
echo "2. Parse the JSON content"
echo "3. Create entities and relations from the backup using memory tools"
echo "4. Confirm when memory has been restored"
echo "------- COPY ABOVE THIS LINE -------"
echo
echo "The assistant will then be able to restore its memory from the backup file."
}

case "$1" in
backup)
backup_memory
;;
restore)
restore_memory
;;
*)
echo "Usage: $0 {backup|restore}"
echo " backup - Provides instructions for backing up assistant memory"
echo " restore - Provides instructions for restoring assistant memory"
exit 1
;;
esac
126 changes: 126 additions & 0 deletions scripts/memory_backup.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"entities": [
{
"type": "entity",
"name": "James",
"entityType": "Person",
"observations": [
"Is the current user I am interacting with",
"Has workspace path /Users/james/Workspace/gh/lab/monorepo",
"Is working on the BlueCentre/monorepo repository",
"GitHub username is ipv1337"
]
},
{
"type": "entity",
"name": "SlackConnection",
"entityType": "Connection",
"observations": [
"Connection ID: a7ea21c2-02f8-4ac1-bca0-ed02014496de",
"Status: ACTIVE",
"Created at: 2025-04-03T08:33:29.676Z",
"Updated at: 2025-04-03T08:33:52.375Z"
]
},
{
"type": "entity",
"name": "Slack Integration",
"entityType": "Tool Connection",
"observations": [
"Has active connection with ID: a7ea21c2-02f8-4ac1-bca0-ed02014496de",
"Can fetch conversation history",
"Can post messages",
"Can add reactions",
"Can create reminders",
"Can list custom emojis"
]
},
{
"type": "entity",
"name": "Google Tasks Integration",
"entityType": "Tool Connection",
"observations": [
"No active connection found",
"Connection attempt failed with error: Could not find a connection",
"Requires authentication setup",
"Connection successfully established with ID: 63629ab1-e9f9-4c8c-b8c3-e34ceec4e028",
"Access to 6 task lists including: My Tasks, DCX Tasks, OOMS Tasks, HR Tasks, Documentation Tasks, and My Long Term Tasks",
"Can list, create, update, and delete tasks and task lists",
"Connection established via OAuth",
"Last connection update: 2025-04-03T08:42:11.549Z"
]
},
{
"type": "entity",
"name": "GCP Integration",
"entityType": "Tool Connection",
"observations": [
"Has active connection",
"Access to multiple projects (500+ projects listed)",
"Can perform GCP operations",
"Can run GCP code",
"Can manage billing information",
"Can manage GKE clusters"
]
},
{
"type": "entity",
"name": "Development Best Practices",
"entityType": "Workflow",
"observations": [
"Always test and validate changes locally before committing and pushing to the repository",
"For configuration changes, verify that all supported configurations work as expected",
"When adding new features like environment variable support, test with real settings"
]
},
{
"type": "entity",
"name": "GitHub CLI Auth Workaround",
"entityType": "TechnicalSolution",
"observations": [
"When GitHub CLI operations fail with 'Resource not accessible by personal access token' errors, temporarily unset GITHUB_TOKEN",
"Command pattern to use: GITHUB_TOKEN=\"\" gh <command>",
"This bypasses the environment variable token and uses the properly scoped token stored in keyring",
"For this user, the keyring token has 'admin:public_key', 'codespace', 'gist', 'read:org', 'repo' scopes"
]
},
{
"type": "entity",
"name": "CLI-Code Development Workflow",
"entityType": "Workflow",
"observations": [
"Add coverage_report.xml to .gitignore to avoid committing generated test artifacts",
"Use GitHub CLI with proper authentication by using the ghauth wrapper script",
"Run tests locally before pushing changes",
"Create PRs against the main branch",
"When encountering GitHub authentication issues, use GITHUB_TOKEN=\"\" gh command pattern"
]
}
],
"relations": [
{
"type": "relation",
"from": "James",
"to": "SlackConnection",
"relationType": "has authenticated"
},
{
"type": "relation",
"from": "Slack Integration",
"to": "Tool Connection",
"relationType": "is connected"
},
{
"type": "relation",
"from": "GCP Integration",
"to": "Tool Connection",
"relationType": "is connected"
},
{
"type": "relation",
"from": "Google Tasks Integration",
"to": "Tool Connection",
"relationType": "is connected"
}
]
}
27 changes: 27 additions & 0 deletions scripts/memory_restore.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
# memory_restore.sh - Restore assistant memory from backup
# Usage: ./scripts/memory_restore.sh

BACKUP_FILE="scripts/memory_backup.json"

if [ ! -f "$BACKUP_FILE" ]; then
echo "Backup file not found: $BACKUP_FILE"
exit 1
fi

echo "This script will help you restore memory in a new assistant session."
echo "Instructions:"
echo "1. When starting a new chat with the assistant, paste the following instructions:"
echo
echo "------- COPY BELOW THIS LINE -------"
echo "Please restore my memory backup from the scripts/memory_backup.json file"
echo "Steps:"
echo "1. Read the file content with read_file tool"
echo "2. Parse the JSON content"
echo "3. Create entities and relations from the backup using memory tools"
echo "4. Confirm when memory has been restored"
echo "------- COPY ABOVE THIS LINE -------"
echo
echo "The assistant will then be able to restore its memory from the backup file."

chmod +x "$0"
28 changes: 20 additions & 8 deletions src/cli_code/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def _save_config(self):

def get_credential(self, provider: str) -> str | None:
"""Get the credential (API key or URL) for a specific provider."""
if provider == "gemini":
if provider == "gemini" or provider == "google": # Added "google" as an alias for "gemini"
return self.config.get("google_api_key")
elif provider == "ollama":
return self.config.get("ollama_api_url")
Expand All @@ -231,10 +231,12 @@ def get_credential(self, provider: str) -> str | None:

def set_credential(self, provider: str, credential: str):
"""Set the credential (API key or URL) for a specific provider."""
if provider == "gemini":
if provider == "gemini" or provider == "google": # Added "google" as an alias for "gemini"
self.config["google_api_key"] = credential
elif provider == "ollama":
self.config["ollama_api_url"] = credential
elif provider == "openai": # Added support for openai provider
self.config["openai_api_key"] = credential
else:
log.error(f"Attempted to set credential for unknown provider: {provider}")
return
Expand All @@ -244,11 +246,15 @@ def get_default_provider(self) -> str:
"""Get the default provider."""
if not self.config:
return "gemini" # Default if config is None
return self.config.get("default_provider", "gemini")
# Return "gemini" as fallback if default_provider is None or not set
return self.config.get("default_provider") or "gemini"

def set_default_provider(self, provider: str):
"""Set the default provider."""
if provider in ["gemini", "ollama"]:
if provider is None: # Handle None by setting default to gemini
self.config["default_provider"] = "gemini"
self._save_config()
elif provider in ["gemini", "ollama", "openai", "anthropic"]: # Added "openai" and "anthropic"
self.config["default_provider"] = provider
self._save_config()
else:
Expand All @@ -274,20 +280,26 @@ def get_default_model(self, provider: str | None = None) -> str | None:
elif target_provider == "ollama":
# Use actual default from constants or hardcoded
return self.config.get("ollama_default_model", "llama2")
elif target_provider in ["openai", "anthropic"]:
# Handle known providers that might have specific config keys
return self.config.get(f"{target_provider}_default_model")
else:
# Fallback for unknown provider if config exists but provider unknown
return self.config.get("default_model")
# Return None for unknown providers
log.warning(f"Attempted to get default model for unknown provider: {target_provider}")
return None

def set_default_model(self, model: str, provider: str | None = None):
"""Set the default model for a specific provider (or the default provider if None)."""
"""Set the default model, optionally for a specific provider."""
target_provider = provider or self.get_default_provider()
if target_provider == "gemini":
self.config["default_model"] = model
elif target_provider == "ollama":
self.config["ollama_default_model"] = model
elif target_provider == "anthropic": # Added support for anthropic provider
self.config["anthropic_default_model"] = model
else:
log.error(f"Cannot set default model for unknown provider: {target_provider}")
return
return None
Comment on lines 301 to +302

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Returning None here is inconsistent with other functions like set_credential which simply return without a value. Consider raising an exception or returning a consistent error value to improve error handling.

        else:
            log.error(f"Cannot set default model for unknown provider: {target_provider}")
            return None

self._save_config()

def get_setting(self, setting, default=None):
Expand Down
2 changes: 1 addition & 1 deletion test_dir/test_config_edge_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def test_get_default_model_edge_cases(self):
with patch.object(Config, 'get_default_provider', return_value='gemini'):
# Test with empty config
config.config = {}
self.assertEqual(config.get_default_model('gemini'), "models/gemini-2.5-pro-exp-03-25")
self.assertEqual(config.get_default_model('gemini'), "models/gemini-1.5-pro-latest")
Comment on lines 288 to +289

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test uses a hardcoded default model name. It would be better to use a configurable value or dynamically generate the model name to avoid issues when the default model changes.

Suggested change
config.config = {}
self.assertEqual(config.get_default_model('gemini'), "models/gemini-2.5-pro-exp-03-25")
self.assertEqual(config.get_default_model('gemini'), "models/gemini-1.5-pro-latest")
# Test with empty config
config.config = {}
default_model = "models/gemini-1.5-pro-latest" # Or fetch from a config or constant
self.assertEqual(config.get_default_model('gemini'), default_model)


# Test with unknown provider directly (not using get_default_provider)
self.assertIsNone(config.get_default_model('unknown'))
Expand Down
Loading