Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
7 changes: 0 additions & 7 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,10 @@ hatch build
# Install this package from local directory.
pip install -e .

# Create logs directory if it doesn't exist
mkdir -p logs

# Create optional data directories
mkdir -p data

# Create .env file if it doesn't exist
if [ ! -f .env ]; then
echo "📝 Creating .env template..."
echo "# Optional: CodeQL database base path" >> .env
echo "CODEQL_DBS_BASE_PATH=$(realpath data)" >> .env
echo "⚠️ Please configure the environment or your .env file with required tokens!"
fi

Expand Down
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
__pycache__
docker/
logs/**/*
.env
.venv
.direnv
Expand Down
5 changes: 0 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ __pycache__/
# C extensions
*.so

# Logs directory
logs/

# Distribution / packaging
.Python
build/
Expand Down Expand Up @@ -186,5 +183,3 @@ config.yaml

#database
*.db
#logs
logs/
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ if [ ! -f ".env" ]; then
fi

docker run \
--volume "$PWD"/logs:/app/logs \
--mount type=bind,src="$PWD"/.env,dst=/app/.env,ro \
${MY_DATA:+--mount type=bind,src=$MY_DATA,dst=/app/my_data} \
${MY_MCP_SERVERS:+--mount type=bind,src=$MY_MCP_SERVERS,dst=/app/my_mcp_servers,ro} \
Expand Down
3 changes: 0 additions & 3 deletions docker/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@
# sudo -E ../docker/run.sh -p seclab_taskflow_agent.personalities.assistant 'explain modems to me please'

touch -a .env
mkdir -p logs
mkdir -p data

docker run -i \
--mount type=bind,src="$PWD",dst=/app \
-e DATA_DIR=/app/data \
-e GITHUB_PERSONAL_ACCESS_TOKEN="$GITHUB_PERSONAL_ACCESS_TOKEN" \
-e COPILOT_TOKEN="$COPILOT_TOKEN" \
"ghcr.io/githubsecuritylab/seclab-taskflow-agent" "$@"
5 changes: 2 additions & 3 deletions src/seclab_taskflow_agent/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@
from .agent import TaskAgent
from .capi import list_tool_call_models
from .available_tools import AvailableTools
from .path_utils import log_file_name

load_dotenv(find_dotenv(usecwd=True))

# only model output or help message should go to stdout, everything else goes to log
logging.getLogger('').setLevel(logging.NOTSET)
log_dir = pathlib.Path("logs")
log_dir.mkdir(parents=True, exist_ok=True)
log_file_handler = RotatingFileHandler(
log_dir.joinpath('task_agent.log'),
log_file_name('task_agent.log'),
maxBytes=1024*1024*10,
backupCount=10)
log_file_handler.setLevel(os.getenv('TASK_AGENT_LOGLEVEL', default='DEBUG'))
Expand Down
4 changes: 2 additions & 2 deletions src/seclab_taskflow_agent/mcp_servers/codeql/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import os
import zipfile
import yaml
from seclab_taskflow_agent.path_utils import log_file_name

# this is a local fork of https://github.com/riga/jsonrpyc modified for our purposes
from . import jsonrpyc
Expand Down Expand Up @@ -45,8 +46,7 @@ def __init__(self,
log_stderr=False):
self.server_options = server_options.copy()
if log_stderr:
os.makedirs("logs", exist_ok=True)
self.stderr_log = f"logs/codeql_stderr_log.log"
self.stderr_log = log_file_name('codeql_stderr_log.log')
self.server_options.append("--log-to-stderr")
else:
self.stderr_log = os.devnull
Expand Down
15 changes: 8 additions & 7 deletions src/seclab_taskflow_agent/mcp_servers/codeql/mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
# SPDX-License-Identifier: MIT

import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='logs/mcp_codeql.log',
filemode='a'
)
from .client import run_query, file_from_uri, list_src_files, _debug_log, search_in_src_archive
from pydantic import Field
#from mcp.server.fastmcp import FastMCP, Context
Expand All @@ -20,7 +14,14 @@
import re
from urllib.parse import urlparse, unquote
import zipfile
from seclab_taskflow_agent.path_utils import mcp_data_dir
from seclab_taskflow_agent.path_utils import mcp_data_dir, log_file_name

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename=log_file_name('mcp_codeql.log'),
filemode='a'
)

mcp = FastMCP("CodeQL")

Expand Down
8 changes: 5 additions & 3 deletions src/seclab_taskflow_agent/mcp_servers/echo/echo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
# SPDX-License-Identifier: MIT

import logging
#from mcp.server.fastmcp import FastMCP
from fastmcp import FastMCP # move to FastMCP 2.0
from seclab_taskflow_agent.path_utils import log_file_name

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='logs/mcp_echo.log',
filename=log_file_name('mcp_echo.log'),
filemode='a'
)
#from mcp.server.fastmcp import FastMCP
from fastmcp import FastMCP # move to FastMCP 2.0

mcp = FastMCP("Echo")

Expand Down
13 changes: 7 additions & 6 deletions src/seclab_taskflow_agent/mcp_servers/logbook/logbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
# SPDX-License-Identifier: MIT

import logging
#from mcp.server.fastmcp import FastMCP
from fastmcp import FastMCP # move to FastMCP 2.0
import json
from pathlib import Path
from seclab_taskflow_agent.path_utils import mcp_data_dir, log_file_name

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='logs/mcp_logbook.log',
filename=log_file_name('mcp_logbook.log'),
filemode='a'
)
#from mcp.server.fastmcp import FastMCP
from fastmcp import FastMCP # move to FastMCP 2.0
import json
from pathlib import Path
from seclab_taskflow_agent.path_utils import mcp_data_dir

mcp = FastMCP("Logbook")

Expand Down
15 changes: 8 additions & 7 deletions src/seclab_taskflow_agent/mcp_servers/memcache/memcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
# SPDX-License-Identifier: MIT

import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='logs/mcp_memcache.log',
filemode='a'
)
#from mcp.server.fastmcp import FastMCP
from fastmcp import FastMCP # move to FastMCP 2.0
import json
Expand All @@ -16,7 +10,14 @@
from typing import Any
from .memcache_backend.dictionary_file import MemcacheDictionaryFileBackend
from .memcache_backend.sqlite import SqliteBackend
from seclab_taskflow_agent.path_utils import mcp_data_dir
from seclab_taskflow_agent.path_utils import mcp_data_dir, log_file_name

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename=log_file_name('mcp_memcache.log'),
filemode='a'
)

mcp = FastMCP("Memcache")

Expand Down
23 changes: 23 additions & 0 deletions src/seclab_taskflow_agent/path_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,26 @@ def mcp_data_dir(packagename: str, mcpname: str, env_override: str | None) -> Pa
p = Path(d).joinpath(packagename).joinpath(mcpname)
p.mkdir(parents=True, exist_ok=True)
return p

def log_dir() -> str:
"""
Get the directory path for storing log files for the seclab-taskflow-agent.

Returns:
str: The path to the log directory.
"""
return platformdirs.user_log_dir(appname="seclab-taskflow-agent",
appauthor="GitHubSecurityLab",
ensure_exists=True)

def log_file_name(filename: str) -> str:
"""
Construct the full path to a log file in the user log directory.

Parameters:
filename (str): The name of the log file.

Returns:
str: The full path to the log file in the user log directory.
"""
return os.path.join(log_dir(), filename)
12 changes: 10 additions & 2 deletions src/seclab_taskflow_agent/render_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
# SPDX-FileCopyrightText: 2025 GitHub
# SPDX-License-Identifier: MIT

import logging
import asyncio
from .path_utils import log_file_name

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename=log_file_name('render_stdout.log'),
filemode='a'
)

async_output = {}
async_output_lock = asyncio.Lock()
Expand Down Expand Up @@ -31,6 +40,5 @@ async def render_model_output(data: str,
data = "** 🤖✏️ Gathering output from async task ... please hold\n"
if data:
if log:
with open('logs/render_stdout.log', 'a') as f:
f.write(data)
logging.debug(data)
print(data, end="", flush=True)