diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 78f4160..6690d4c 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -11,12 +11,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" + cache: "pip" - name: Install linting tools run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64e6124..ee2b346 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,18 +12,18 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" + cache: "pip" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install pytest - name: Run tests run: pytest tests/ -v @@ -33,12 +33,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Helm - uses: azure/setup-helm@v3 + uses: azure/setup-helm@v4 with: version: v3.12.3 - name: Lint Helm chart - run: helm lint helm/ + run: helm lint infra/helm/agentic-ai-assistant/ diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 33d08f6..10024c9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -9,12 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" + cache: "pip" - name: Install MkDocs run: | diff --git a/Dockerfile b/Dockerfile index e056fd8..d33c97c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,29 +2,38 @@ # HelixAgent Dockerfile # ============================== -# Base image +# ── Stage 1: Build Java planner JAR ───────────────────────────────────────── +FROM maven:3.9-eclipse-temurin-11-slim AS java-builder +WORKDIR /build +COPY java/ java/ +RUN cd java && mvn package -q + +# ── Stage 2: Runtime image ────────────────────────────────────────────────── FROM python:3.10-slim -# Set working directory WORKDIR /app -# Install system dependencies +# System dependencies (C++ compiler for libvector.so) RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ git \ curl \ && rm -rf /var/lib/apt/lists/* -# Copy requirements first for caching +# Python dependencies COPY requirements.txt . - -# Install Python dependencies RUN pip install --upgrade pip \ && pip install -r requirements.txt # Copy project files COPY . . +# Compile C++ cosine-similarity library +RUN g++ -O3 -shared -std=c++17 -fPIC agent/cpp/vector.cpp -o agent/cpp/libvector.so + +# Copy compiled Java planner JAR from build stage +COPY --from=java-builder /build/java/target/planner.jar agent/java/planner.jar + # Expose ports for FastAPI (8000) and Streamlit (8501) EXPOSE 8000 8501 diff --git a/Makefile b/Makefile index 921e78c..5b87a07 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,9 @@ # make helm-up # upgrade Helm release (local Kube context) # make tf-plan # terraform plan (infra/terraform) # make tf-apply # terraform apply (infra/terraform) +# make cpp-build # compile C++ cosine-similarity library +# make java-build # compile Java planner JAR via Maven +# make build-native # compile both C++ and Java artifacts # -------------------------------------------------------------------- PYTHON ?= python @@ -37,6 +40,23 @@ lint: dev: uvicorn api.main:app --reload --port 8000 +# -------------------------------------------------------------------- +# Native build targets +# -------------------------------------------------------------------- +.PHONY: cpp-build +cpp-build: + g++ -O3 -shared -std=c++17 -fPIC agent/cpp/vector.cpp -o agent/cpp/libvector.so + @echo "✓ agent/cpp/libvector.so built" + +.PHONY: java-build +java-build: + cd java && mvn package -q + @echo "✓ agent/java/planner.jar built" + +.PHONY: build-native +build-native: cpp-build java-build + @echo "✓ All native artifacts built" + # -------------------------------------------------------------------- # Docker targets # -------------------------------------------------------------------- diff --git a/README.md b/README.md index 56716b9..ee6cfcc 100644 --- a/README.md +++ b/README.md @@ -5,24 +5,37 @@ An **AI-powered agent framework** designed for modular automation, reasoning, and decision-making. Capstone-ready • Production-aware • Built for extensibility. -### 📊 Project Health & Features + HelixAgent — Autonomous AI Agent System + +![Python](https://img.shields.io/badge/Python-3.10+-blue?logo=python) +![TypeScript](https://img.shields.io/badge/TypeScript-Agent%20Layer-blue?logo=typescript) +![Go](https://img.shields.io/badge/Go-Backend-blue?logo=go) +![LLM](https://img.shields.io/badge/LLM-Integrated-purple) +![Agents](https://img.shields.io/badge/AI-Agents-orange) +![LangChain](https://img.shields.io/badge/LangChain-Orchestration-green) +![RAG](https://img.shields.io/badge/RAG-Pipeline-blue) +![FastAPI](https://img.shields.io/badge/FastAPI-Inference-green?logo=fastapi) +![Streamlit](https://img.shields.io/badge/Streamlit-UI-red?logo=streamlit) +![Docker](https://img.shields.io/badge/Docker-Containerized-blue?logo=docker) +![Kubernetes](https://img.shields.io/badge/Kubernetes-Orchestrated-blue?logo=kubernetes) +![Helm](https://img.shields.io/badge/Helm-Charts-blue?logo=helm) +![CI/CD](https://img.shields.io/badge/CI/CD-GitHub%20Actions-black?logo=githubactions) +![Terraform](https://img.shields.io/badge/Terraform-IaC-purple?logo=terraform) +![Ansible](https://img.shields.io/badge/Ansible-Automation-red?logo=ansible) +![Observability](https://img.shields.io/badge/Observability-Enabled-orange) +![Grafana](https://img.shields.io/badge/Grafana-Monitoring-orange?logo=grafana) +![Prometheus](https://img.shields.io/badge/Prometheus-Metrics-yellow?logo=prometheus) +![License](https://img.shields.io/badge/License-MIT-green) +![Status](https://img.shields.io/badge/Status-Production--Ready-brightgreen) +![Stars](https://img.shields.io/github/stars/Trojan3877/HelixAgent?style=social) +![Forks](https://img.shields.io/github/forks/Trojan3877/HelixAgent?style=social) +![Autonomous](https://img.shields.io/badge/Autonomous-Agents-critical) +![Multi-Agent](https://img.shields.io/badge/Multi--Agent-System-blue) +![Real-Time](https://img.shields.io/badge/Real--Time-Decisioning-green) +![Scalable](https://img.shields.io/badge/Scale-Horizontal-blue) +![Microservices](https://img.shields.io/badge/Architecture-Microservices-black) +![Latency](https://img.shields.io/badge/Latency-Low-critical) -![CI/CD](https://github.com/Trojan3877/HelixAgent/actions/workflows/ci.yml/badge.svg) -![Lint](https://github.com/Trojan3877/HelixAgent/actions/workflows/ci-cd.yml/badge.svg?label=Lint) -![Docker](https://img.shields.io/badge/Docker-ready-brightgreen?logo=docker&logoColor=white) -![Helm](https://img.shields.io/badge/Helm-Packaged-brightgreen?logo=helm&logoColor=white) -![Observability](https://img.shields.io/badge/Monitoring-Prometheus%20%26%20OpenTelemetry-brightgreen?logo=prometheus&logoColor=white) -![Last Commit](https://img.shields.io/github/last-commit/Trojan3877/HelixAgent?logo=git&label=Last%20Commit&color=brightgreen) -![Repo Size](https://img.shields.io/github/repo-size/Trojan3877/HelixAgent?logo=github&label=Repo%20Size&color=brightgreen) -![Contributions](https://img.shields.io/badge/Contributions-Welcome-brightgreen?logo=github) -![Style](https://img.shields.io/badge/Code%20Style-Black-brightgreen?logo=python&logoColor=white) -![Docs](https://img.shields.io/badge/Docs-MkDocs%20Live-brightgreen?logo=readthedocs&logoColor=white) - - - ---- - -## 📖 Overview HelixAgent is a **modular AI agent framework** that enables automation of tasks, reasoning chains, and integration with external APIs. It is designed for: diff --git a/agent/agent_core.py b/agent/agent_core.py index bc388c6..3977169 100644 --- a/agent/agent_core.py +++ b/agent/agent_core.py @@ -3,100 +3,202 @@ ============= Main orchestration class for the Agentic-AI-Assistant. -▪ Loads planner (Java) via JPype bridge -▪ Calls high-performance vector tool (C++) via ctypes -▪ Handles LLM interaction + tool routing - -Requirements: - - langchain, langgraph - - jpype1 (Python ↔ Java bridge) - - ctypes (std lib) (Python ↔ C++) +▪ Loads planner (Java) via JPype bridge when the compiled JAR is present +▪ Calls high-performance vector tool (C++) via ctypes when libvector.so exists +▪ Falls back to pure-Python equivalents when native artifacts are unavailable +▪ Handles tool routing via LangGraph StateGraph + +Requirements (see requirements.txt): + - langgraph (graph orchestration) + - jpype1 (Python ↔ Java bridge, optional at runtime) + - ctypes (stdlib – Python ↔ C++) """ -from langgraph import Graph # pip install langgraph -import jpype import ctypes +import logging +import math from pathlib import Path - -# --- Load Java Planner ------------------------------------------------------- - -JAR_PATH = Path(__file__).parent / "java" / "planner.jar" -if not jpype.isJVMStarted(): - jpype.startJVM(classpath=[str(JAR_PATH)]) - -JavaPlanner = jpype.JClass("com.trojan.ai.Planner") - -# --- Load C++ Vector Utility ------------------------------------------------- - -lib_vec = ctypes.cdll.LoadLibrary(str(Path(__file__).parent / "cpp" / "libvector.so")) -lib_vec.cosine_similarity.restype = ctypes.c_double -lib_vec.cosine_similarity.argtypes = (ctypes.POINTER(ctypes.c_double), - ctypes.POINTER(ctypes.c_double), - ctypes.c_int) - -def cosine_sim(py_vec1, py_vec2): - """Wrapper for C++ cosine similarity""" - length = len(py_vec1) - array_type = ctypes.c_double * length - v1 = array_type(*py_vec1) - v2 = array_type(*py_vec2) - return lib_vec.cosine_similarity(v1, v2, length) - -# --- LangGraph Agent --------------------------------------------------------- - +from typing import TypedDict + +from langgraph.graph import END, StateGraph + +log = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Java Planner (optional – requires compiled agent/java/planner.jar) +# --------------------------------------------------------------------------- +_JavaPlanner = None +_JAR_PATH = Path(__file__).parent / "java" / "planner.jar" + +try: + import jpype # noqa: PLC0415 + + if _JAR_PATH.exists(): + if not jpype.isJVMStarted(): + jpype.startJVM(classpath=[str(_JAR_PATH)]) + _JavaPlanner = jpype.JClass("com.trojan.ai.Planner") + log.info("Java planner loaded from %s", _JAR_PATH) + else: + log.info("planner.jar not found at %s – using Python fallback planner.", _JAR_PATH) +except Exception as _e: # noqa: BLE001 + log.warning("Java planner unavailable (%s) – using Python fallback planner.", _e) + + +# --------------------------------------------------------------------------- +# C++ Vector Utility (optional – requires compiled agent/cpp/libvector.so) +# --------------------------------------------------------------------------- +_lib_vec = None +_LIB_PATH = Path(__file__).parent / "cpp" / "libvector.so" + +try: + if _LIB_PATH.exists(): + _lib_vec = ctypes.cdll.LoadLibrary(str(_LIB_PATH)) + _lib_vec.cosine_similarity.restype = ctypes.c_double + _lib_vec.cosine_similarity.argtypes = ( + ctypes.POINTER(ctypes.c_double), + ctypes.POINTER(ctypes.c_double), + ctypes.c_int, + ) + log.info("C++ vector library loaded from %s", _LIB_PATH) + else: + log.info("libvector.so not found at %s – using pure-Python cosine similarity.", _LIB_PATH) +except Exception as _e: # noqa: BLE001 + log.warning("C++ vector library unavailable (%s) – using pure-Python fallback.", _e) + + +def cosine_sim(py_vec1: list, py_vec2: list) -> float: + """Return cosine similarity. Uses C++ library when available.""" + if _lib_vec is not None: + length = len(py_vec1) + array_type = ctypes.c_double * length + v1 = array_type(*py_vec1) + v2 = array_type(*py_vec2) + return _lib_vec.cosine_similarity(v1, v2, length) + + # Pure-Python fallback + dot = sum(a * b for a, b in zip(py_vec1, py_vec2)) + mag1 = math.sqrt(sum(a * a for a in py_vec1)) + mag2 = math.sqrt(sum(b * b for b in py_vec2)) + return dot / (mag1 * mag2) if mag1 * mag2 else 0.0 + + +# --------------------------------------------------------------------------- +# Web-search tool (optional – requires duckduckgo-search) +# --------------------------------------------------------------------------- +def _web_search(query: str) -> str: + try: + from agent.tools.web_search import search_and_summarize # noqa: PLC0415 + + return search_and_summarize(query) + except Exception as exc: # noqa: BLE001 + return f"[web_search unavailable: {exc}]" + + +# --------------------------------------------------------------------------- +# LangGraph State +# --------------------------------------------------------------------------- +class AgentState(TypedDict): + prompt: str + steps: list + idx: int + history: list + + +# --------------------------------------------------------------------------- +# AgenticAssistant +# --------------------------------------------------------------------------- class AgenticAssistant: """ High-level Agent that delegates: - 1. planning → Java - 2. heavy math → C++ - 3. LLM calls → LangGraph tools + 1. planning → Java planner (falls back to keyword heuristic) + 2. vector similarity → C++ library (falls back to pure Python) + 3. web search → DuckDuckGo tool + 4. orchestration → LangGraph StateGraph """ - def __init__(self): - self.planner = JavaPlanner() - - # Build LangGraph workflow - self.graph = Graph() - self.graph.add_node("plan", self.do_plan) - self.graph.add_node("execute", self.do_execute) - self.graph.set_entrypoint("plan") - - # --------------------------------------------------------------------- # - # Node functions - # --------------------------------------------------------------------- # + def __init__(self) -> None: + self._java_planner = _JavaPlanner() if _JavaPlanner is not None else None + + graph = StateGraph(AgentState) + graph.add_node("plan", self._do_plan) + graph.add_node("execute", self._do_execute) + graph.set_entry_point("plan") + graph.add_edge("plan", "execute") + graph.add_conditional_edges( + "execute", + lambda s: "end" if s["idx"] >= len(s["steps"]) else "execute", + {"execute": "execute", "end": END}, + ) + self._graph = graph.compile() + + # ---------------------------------------------------------------------- # + # Private helpers + # ---------------------------------------------------------------------- # + + def _plan_fallback(self, prompt: str) -> list: + """Keyword-based planner used when the Java JAR is not present.""" + steps: list = [] + lower = prompt.lower() + if "vector" in lower: + steps.append("vector_similarity") + if "search" in lower or "web" in lower: + steps.append("web_search") + steps.append("llm_summary") + return steps + + # ---------------------------------------------------------------------- # + # LangGraph node functions + # ---------------------------------------------------------------------- # + + def _do_plan(self, state: AgentState) -> AgentState: + """Decompose the user prompt into an ordered list of steps.""" + prompt = state["prompt"] + if self._java_planner is not None: + steps = [str(s) for s in self._java_planner.createPlan(prompt)] + else: + steps = self._plan_fallback(prompt) + log.debug("Plan: %s", steps) + return {"prompt": prompt, "steps": steps, "idx": 0, "history": []} - def do_plan(self, user_msg: str) -> dict: - """Call Java planner to decompose task.""" - steps = self.planner.createPlan(user_msg) - return {"steps": steps, "idx": 0, "history": []} + def _do_execute(self, state: AgentState) -> AgentState: + """Execute the next pending step and advance the index.""" + steps = state["steps"] + idx = state["idx"] + history = list(state.get("history", [])) - def do_execute(self, state: dict): - """Execute each step (placeholder — will route tools later).""" - steps, idx = state["steps"], state["idx"] if idx >= len(steps): - return "DONE" + return state current = steps[idx] - # Very simple routing example - if current.lower().startswith("vector"): - result = cosine_sim([1, 0, 1], [0.5, 0, 0.5]) + if current == "vector_similarity": + score = cosine_sim([1, 0, 1], [0.5, 0, 0.5]) + result = f"cosine_similarity([1,0,1], [0.5,0,0.5]) = {score:.4f}" + elif current == "web_search": + result = _web_search(state["prompt"]) else: - result = f"LLM-TODO: {current}" + result = f"[{current}] Processed: {state['prompt'][:120]}" + + log.debug("Step %d (%s): %s", idx, current, result) + history.append(result) + return {"prompt": state["prompt"], "steps": steps, "idx": idx + 1, "history": history} - state["history"].append(result) - state["idx"] += 1 - return state + # ---------------------------------------------------------------------- # + # Public API + # ---------------------------------------------------------------------- # - # --------------------------------------------------------------------- # + def run(self, prompt: str) -> str: + """Run a full agent cycle and return the combined output.""" + initial: AgentState = {"prompt": prompt, "steps": [], "idx": 0, "history": []} + final_state = self._graph.invoke(initial) + history = final_state.get("history", []) + return "\n".join(str(h) for h in history) if history else f"[HelixAgent] {prompt}" - def run(self, prompt: str): - """Run a full agent cycle.""" - return self.graph.run(prompt) -# ------------------------------------------------------------------------- # +# --------------------------------------------------------------------------- # Quick CLI demo -# ------------------------------------------------------------------------- # +# --------------------------------------------------------------------------- if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) assistant = AgenticAssistant() output = assistant.run("Compare vectors and then draft summary") print("Agent Output:", output) diff --git a/agent/java/.gitkeep b/agent/java/.gitkeep new file mode 100644 index 0000000..b9fa843 --- /dev/null +++ b/agent/java/.gitkeep @@ -0,0 +1,2 @@ +# Compiled Java planner JAR is placed here by `make java-build`. +# See java/pom.xml for build instructions. diff --git a/agent/tools/web_search.py b/agent/tools/web_search.py index 3c9587d..0389b6b 100644 --- a/agent/tools/web_search.py +++ b/agent/tools/web_search.py @@ -15,10 +15,10 @@ 3. Returns a concatenated summary string Dependencies: - pip install duckduckgo-search==5.2.2 + pip install ddgs """ -from duckduckgo_search import DDGS +from ddgs import DDGS def search_and_summarize(query: str, max_results: int = 5) -> str: """ diff --git a/api/main.py b/api/main.py index a23545b..15e305b 100644 --- a/api/main.py +++ b/api/main.py @@ -7,6 +7,7 @@ exposes core routes for agent inference. """ +import logging import os from fastapi import FastAPI @@ -51,15 +52,15 @@ async def predict(payload: PredictRequest): Returns: { "result": "" } - - Note: Full agent integration (LangGraph + Java planner) is wired in - agent/agent_core.py. This endpoint serves as the HTTP interface; swap - in AgenticAssistant().run(prompt) once the Java JAR and C++ .so are built. """ - # Placeholder response – replace with agent invocation once built: - # from agent.agent_core import AgenticAssistant - # result = AgenticAssistant().run(payload.prompt) - result = f"[HelixAgent] received: {payload.prompt}" + try: + from agent.agent_core import AgenticAssistant # noqa: PLC0415 + + assistant = AgenticAssistant() + result = assistant.run(payload.prompt) + except Exception as exc: # noqa: BLE001 + result = f"[HelixAgent] received: {payload.prompt}" + logging.getLogger(__name__).warning("Agent core unavailable: %s", exc) return {"result": result} diff --git a/infra/helm/agentic-ai-assistant/templates/_helpers.tpl b/infra/helm/agentic-ai-assistant/templates/_helpers.tpl new file mode 100644 index 0000000..065e692 --- /dev/null +++ b/infra/helm/agentic-ai-assistant/templates/_helpers.tpl @@ -0,0 +1,49 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "agentic-ai-assistant.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "agentic-ai-assistant.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "agentic-ai-assistant.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "agentic-ai-assistant.labels" -}} +helm.sh/chart: {{ include "agentic-ai-assistant.chart" . }} +{{ include "agentic-ai-assistant.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "agentic-ai-assistant.selectorLabels" -}} +app.kubernetes.io/name: {{ include "agentic-ai-assistant.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 0000000..84fdb4b --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + com.trojan.ai + planner + 1.0.0 + jar + + HelixAgent Java Planner + Converts high-level prompts into ordered task steps for the HelixAgent framework. + + + 11 + 11 + UTF-8 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + ${project.basedir}/../agent/java + planner + + + + + diff --git a/java/src/main/java/com/trojan/ai/Planner.java b/java/src/main/java/com/trojan/ai/Planner.java new file mode 100644 index 0000000..8a57f7b --- /dev/null +++ b/java/src/main/java/com/trojan/ai/Planner.java @@ -0,0 +1,42 @@ +package com.trojan.ai; + +import java.util.ArrayList; +import java.util.List; + +/** + * High-level task planner for HelixAgent. + * Converts user prompts into ordered sequences of steps. + */ +public class Planner { + + /** + * Create an execution plan from a natural language prompt. + * + * @param prompt User's high-level request + * @return Ordered list of action steps (e.g., ["web_search", "llm_summary"]) + */ + public List createPlan(String prompt) { + List steps = new ArrayList<>(); + String lower = prompt.toLowerCase(); + + // Simple keyword-based planning (can be replaced with LLM later) + if (lower.contains("vector") || lower.contains("similarity")) { + steps.add("vector_similarity"); + } + + if (lower.contains("search") || lower.contains("web")) { + steps.add("web_search"); + } + + if (lower.contains("summarize") || lower.contains("summary")) { + steps.add("llm_summary"); + } + + // Always add a reasoning step at the end + if (steps.isEmpty()) { + steps.add("llm_reasoning"); + } + + return steps; + } +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f8caed7..2142f49 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,6 +33,15 @@ pytest-cov==5.0.0 coverage==7.5.1 httpx==0.27.0 +# --- Agent orchestration --- +langgraph==1.1.6 +jpype1==1.6.0 + +# --- Cloud / data-source tools --- +boto3==1.42.83 +snowflake-connector-python==4.4.0 +ddgs==9.12.1 + # --- Documentation --- mkdocs==1.5.3 mkdocs-material==9.5.15 diff --git a/src/main.py b/src/main.py index 452189e..cd15260 100644 --- a/src/main.py +++ b/src/main.py @@ -40,15 +40,17 @@ def main() -> None: log.info("HelixAgent starting...") log.info(f"Prompt: {args.prompt}") - # Full agent invocation (requires Java JAR + C++ .so to be compiled): - # from agent.agent_core import AgenticAssistant - # assistant = AgenticAssistant() - # output = assistant.run(args.prompt) - # print("Agent Output:", output) - - # Smoke-test path (no native deps needed): - log.info("Agent core not yet wired – running smoke test only.") - print(f"[HelixAgent] Echo: {args.prompt}") + try: + from agent.agent_core import AgenticAssistant # noqa: E402 + + log.info("Initializing agent core...") + assistant = AgenticAssistant() + output = assistant.run(args.prompt) + log.info("Agent run complete.") + print(f"Agent Output: {output}") + except Exception as exc: # noqa: BLE001 + log.warning(f"Agent core unavailable ({exc}); running echo mode.") + print(f"[HelixAgent] Echo: {args.prompt}") if __name__ == "__main__":