cite-agent 1.3.5__py3-none-any.whl → 1.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cite-agent might be problematic. Click here for more details.
- cite_agent/__version__.py +1 -1
- cite_agent/cli.py +13 -0
- cite_agent/enhanced_ai_agent.py +90 -24
- cite_agent/project_detector.py +148 -0
- {cite_agent-1.3.5.dist-info → cite_agent-1.3.6.dist-info}/METADATA +1 -1
- {cite_agent-1.3.5.dist-info → cite_agent-1.3.6.dist-info}/RECORD +10 -9
- {cite_agent-1.3.5.dist-info → cite_agent-1.3.6.dist-info}/WHEEL +0 -0
- {cite_agent-1.3.5.dist-info → cite_agent-1.3.6.dist-info}/entry_points.txt +0 -0
- {cite_agent-1.3.5.dist-info → cite_agent-1.3.6.dist-info}/licenses/LICENSE +0 -0
- {cite_agent-1.3.5.dist-info → cite_agent-1.3.6.dist-info}/top_level.txt +0 -0
cite_agent/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.3.
|
|
1
|
+
__version__ = "1.3.6"
|
cite_agent/cli.py
CHANGED
|
@@ -256,6 +256,19 @@ class NocturnalCLI:
|
|
|
256
256
|
if not await self.initialize():
|
|
257
257
|
return
|
|
258
258
|
|
|
259
|
+
# Detect if user is in a project directory (R, Python, Node, Jupyter, etc.)
|
|
260
|
+
try:
|
|
261
|
+
from .project_detector import ProjectDetector
|
|
262
|
+
detector = ProjectDetector()
|
|
263
|
+
project_info = detector.detect_project()
|
|
264
|
+
|
|
265
|
+
if project_info:
|
|
266
|
+
# Show project banner
|
|
267
|
+
banner = detector.format_project_banner(project_info)
|
|
268
|
+
self.console.print(banner, style="dim")
|
|
269
|
+
except:
|
|
270
|
+
pass # Silently skip if detection fails
|
|
271
|
+
|
|
259
272
|
self.console.print("\n[bold]🤖 Interactive Mode[/] — Type your questions or 'quit' to exit")
|
|
260
273
|
self.console.rule(style="magenta")
|
|
261
274
|
|
cite_agent/enhanced_ai_agent.py
CHANGED
|
@@ -1698,25 +1698,20 @@ class EnhancedNocturnalAgent:
|
|
|
1698
1698
|
|
|
1699
1699
|
elif response.status == 503:
|
|
1700
1700
|
# Backend AI service temporarily unavailable (Cerebras/Groq rate limited)
|
|
1701
|
-
# Auto-retry with exponential backoff
|
|
1702
|
-
max_retries = 3
|
|
1703
|
-
retry_delays = [5, 15, 30] # seconds
|
|
1701
|
+
# Auto-retry silently with exponential backoff
|
|
1704
1702
|
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
print(f"\r⏱️ Retrying in {remaining}s...", end='', flush=True)
|
|
1713
|
-
await asyncio.sleep(1)
|
|
1714
|
-
print("\r🔄 Retrying now... ")
|
|
1703
|
+
print("\n💭 Thinking... (backend is busy, retrying automatically)")
|
|
1704
|
+
|
|
1705
|
+
import asyncio
|
|
1706
|
+
retry_delays = [5, 15, 30] # Exponential backoff
|
|
1707
|
+
|
|
1708
|
+
for retry_num, delay in enumerate(retry_delays):
|
|
1709
|
+
await asyncio.sleep(delay)
|
|
1715
1710
|
|
|
1716
1711
|
# Retry the request
|
|
1717
1712
|
async with self.session.post(url, json=payload, headers=headers, timeout=60) as retry_response:
|
|
1718
1713
|
if retry_response.status == 200:
|
|
1719
|
-
# Success
|
|
1714
|
+
# Success!
|
|
1720
1715
|
data = await retry_response.json()
|
|
1721
1716
|
response_text = data.get('response', '')
|
|
1722
1717
|
tokens = data.get('tokens_used', 0)
|
|
@@ -1739,17 +1734,19 @@ class EnhancedNocturnalAgent:
|
|
|
1739
1734
|
return ChatResponse(
|
|
1740
1735
|
response=response_text,
|
|
1741
1736
|
tokens_used=tokens,
|
|
1742
|
-
|
|
1743
|
-
|
|
1737
|
+
tools_used=all_tools,
|
|
1738
|
+
model=data.get('model', 'llama-3.3-70b'),
|
|
1739
|
+
timestamp=data.get('timestamp', datetime.now(timezone.utc).isoformat()),
|
|
1740
|
+
api_results=api_results
|
|
1744
1741
|
)
|
|
1745
1742
|
elif retry_response.status != 503:
|
|
1746
1743
|
# Different error, stop retrying
|
|
1747
1744
|
break
|
|
1748
1745
|
|
|
1749
|
-
# All retries
|
|
1746
|
+
# All retries exhausted
|
|
1750
1747
|
return ChatResponse(
|
|
1751
|
-
response="❌ Service
|
|
1752
|
-
error_message="Service
|
|
1748
|
+
response="❌ Service unavailable. Please try again in a few minutes.",
|
|
1749
|
+
error_message="Service unavailable after retries"
|
|
1753
1750
|
)
|
|
1754
1751
|
|
|
1755
1752
|
elif response.status == 200:
|
|
@@ -2667,7 +2664,8 @@ class EnhancedNocturnalAgent:
|
|
|
2667
2664
|
# Quick check if query might need shell
|
|
2668
2665
|
question_lower = request.question.lower()
|
|
2669
2666
|
might_need_shell = any(word in question_lower for word in [
|
|
2670
|
-
'directory', 'folder', 'where', 'find', 'list', 'files', 'look', 'search', 'check', 'into'
|
|
2667
|
+
'directory', 'folder', 'where', 'find', 'list', 'files', 'look', 'search', 'check', 'into',
|
|
2668
|
+
'show', 'open', 'read', 'display', 'cat', 'view', 'contents', '.r', '.py', '.csv', '.ipynb'
|
|
2671
2669
|
])
|
|
2672
2670
|
|
|
2673
2671
|
if might_need_shell and self.shell_session:
|
|
@@ -2679,19 +2677,28 @@ Previous conversation: {json.dumps(self.conversation_history[-2:]) if self.conve
|
|
|
2679
2677
|
|
|
2680
2678
|
Respond ONLY with JSON:
|
|
2681
2679
|
{{
|
|
2682
|
-
"action": "pwd|ls|find|none",
|
|
2680
|
+
"action": "pwd|ls|find|read_file|none",
|
|
2683
2681
|
"search_target": "cm522" (if find),
|
|
2684
2682
|
"search_path": "~/Downloads" (if find),
|
|
2685
|
-
"target_path": "/full/path" (if ls on previous result)
|
|
2683
|
+
"target_path": "/full/path" (if ls on previous result),
|
|
2684
|
+
"file_path": "/full/path/to/file.R" (if read_file)
|
|
2686
2685
|
}}
|
|
2687
2686
|
|
|
2688
2687
|
Examples:
|
|
2689
2688
|
"where am i?" → {{"action": "pwd"}}
|
|
2690
2689
|
"what files here?" → {{"action": "ls"}}
|
|
2691
|
-
"find cm522
|
|
2692
|
-
"look into it" + Previous: "Found /path
|
|
2690
|
+
"find cm522" → {{"action": "find", "search_target": "cm522"}}
|
|
2691
|
+
"look into it" + Previous: "Found /path" → {{"action": "ls", "target_path": "/path"}}
|
|
2692
|
+
"show me calculate_betas.R" → {{"action": "read_file", "file_path": "calculate_betas.R"}}
|
|
2693
|
+
"open regression.R" → {{"action": "read_file", "file_path": "regression.R"}}
|
|
2694
|
+
"read that file" + Previous: "regression.R" → {{"action": "read_file", "file_path": "regression.R"}}
|
|
2695
|
+
"display analysis.py" → {{"action": "read_file", "file_path": "analysis.py"}}
|
|
2696
|
+
"cat data.csv" → {{"action": "read_file", "file_path": "data.csv"}}
|
|
2697
|
+
"what columns does it have?" + Previous: file was shown → {{"action": "none"}} (LLM will parse from conversation)
|
|
2693
2698
|
"Tesla revenue" → {{"action": "none"}}
|
|
2694
2699
|
|
|
2700
|
+
KEY: If query mentions a specific FILENAME (*.R, *.py, *.csv), use read_file, NOT find!
|
|
2701
|
+
|
|
2695
2702
|
JSON:"""
|
|
2696
2703
|
|
|
2697
2704
|
try:
|
|
@@ -2749,6 +2756,65 @@ JSON:"""
|
|
|
2749
2756
|
"search_results": f"No directories matching '{search_target}' found in {search_path}"
|
|
2750
2757
|
}
|
|
2751
2758
|
tools_used.append("shell_execution")
|
|
2759
|
+
|
|
2760
|
+
elif shell_action == "read_file":
|
|
2761
|
+
# NEW: Read and inspect file (R, Python, CSV, etc.)
|
|
2762
|
+
import re # Import at function level
|
|
2763
|
+
|
|
2764
|
+
file_path = plan.get("file_path", "")
|
|
2765
|
+
if not file_path and might_need_shell:
|
|
2766
|
+
# Try to infer from query (e.g., "show me calculate_betas.R")
|
|
2767
|
+
filenames = re.findall(r'([a-zA-Z0-9_-]+\.[a-zA-Z]{1,4})', request.question)
|
|
2768
|
+
if filenames:
|
|
2769
|
+
# Check if file exists in current directory
|
|
2770
|
+
pwd = self.execute_command("pwd").strip()
|
|
2771
|
+
file_path = f"{pwd}/{filenames[0]}"
|
|
2772
|
+
|
|
2773
|
+
if file_path:
|
|
2774
|
+
if debug_mode:
|
|
2775
|
+
print(f"🔍 READING FILE: {file_path}")
|
|
2776
|
+
|
|
2777
|
+
# Read file content (first 100 lines to detect structure)
|
|
2778
|
+
cat_output = self.execute_command(f"head -100 {file_path}")
|
|
2779
|
+
|
|
2780
|
+
if not cat_output.startswith("ERROR"):
|
|
2781
|
+
# Detect file type and extract structure
|
|
2782
|
+
file_ext = file_path.split('.')[-1].lower()
|
|
2783
|
+
|
|
2784
|
+
# Extract column/variable info based on file type
|
|
2785
|
+
columns_info = ""
|
|
2786
|
+
if file_ext in ['csv', 'tsv']:
|
|
2787
|
+
# CSV: first line is usually headers
|
|
2788
|
+
first_line = cat_output.split('\n')[0] if cat_output else ""
|
|
2789
|
+
columns_info = f"CSV columns: {first_line}"
|
|
2790
|
+
elif file_ext in ['r', 'rmd']:
|
|
2791
|
+
# R script: look for dataframe column references (df$columnname)
|
|
2792
|
+
column_refs = re.findall(r'\$(\w+)', cat_output)
|
|
2793
|
+
unique_cols = list(dict.fromkeys(column_refs))[:10]
|
|
2794
|
+
if unique_cols:
|
|
2795
|
+
columns_info = f"Detected columns/variables: {', '.join(unique_cols)}"
|
|
2796
|
+
elif file_ext == 'py':
|
|
2797
|
+
# Python: look for DataFrame['column'] or df.column
|
|
2798
|
+
column_refs = re.findall(r'\[[\'""](\w+)[\'"]\]|\.(\w+)', cat_output)
|
|
2799
|
+
unique_cols = list(dict.fromkeys([c[0] or c[1] for c in column_refs if c[0] or c[1]]))[:10]
|
|
2800
|
+
if unique_cols:
|
|
2801
|
+
columns_info = f"Detected columns/attributes: {', '.join(unique_cols)}"
|
|
2802
|
+
|
|
2803
|
+
api_results["file_context"] = {
|
|
2804
|
+
"file_path": file_path,
|
|
2805
|
+
"file_type": file_ext,
|
|
2806
|
+
"content_preview": cat_output[:2000], # First 2000 chars
|
|
2807
|
+
"structure": columns_info,
|
|
2808
|
+
"full_content": cat_output # Full content for analysis
|
|
2809
|
+
}
|
|
2810
|
+
tools_used.append("file_read")
|
|
2811
|
+
|
|
2812
|
+
if debug_mode:
|
|
2813
|
+
print(f"🔍 FILE STRUCTURE: {columns_info}")
|
|
2814
|
+
else:
|
|
2815
|
+
api_results["file_context"] = {
|
|
2816
|
+
"error": f"Could not read file: {file_path}"
|
|
2817
|
+
}
|
|
2752
2818
|
|
|
2753
2819
|
except Exception as e:
|
|
2754
2820
|
if debug_mode:
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Generic project detection - works with ANY IDE/project type
|
|
4
|
+
Not RStudio-specific - detects R, Python, Node, Jupyter, etc.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Dict, List, Optional, Any
|
|
10
|
+
import glob
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProjectDetector:
|
|
14
|
+
"""Detects project type and provides context"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, working_dir: Optional[str] = None):
|
|
17
|
+
self.working_dir = Path(working_dir or os.getcwd())
|
|
18
|
+
|
|
19
|
+
def detect_project(self) -> Optional[Dict[str, Any]]:
|
|
20
|
+
"""
|
|
21
|
+
Detect what kind of project user is working in
|
|
22
|
+
Returns project info or None if not in a project
|
|
23
|
+
"""
|
|
24
|
+
project_info = {
|
|
25
|
+
"type": None,
|
|
26
|
+
"name": None,
|
|
27
|
+
"recent_files": [],
|
|
28
|
+
"description": None
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# Check for R project (.Rproj file OR 2+ .R files)
|
|
32
|
+
rproj_files = list(self.working_dir.glob("*.Rproj"))
|
|
33
|
+
r_files = list(self.working_dir.glob("*.R")) + list(self.working_dir.glob("*.Rmd"))
|
|
34
|
+
|
|
35
|
+
if rproj_files:
|
|
36
|
+
project_info["type"] = "R"
|
|
37
|
+
project_info["name"] = rproj_files[0].stem
|
|
38
|
+
project_info["recent_files"] = self._get_recent_files([".R", ".Rmd", ".qmd"])
|
|
39
|
+
project_info["description"] = f"R/RStudio project: {project_info['name']}"
|
|
40
|
+
return project_info
|
|
41
|
+
elif len(r_files) >= 2:
|
|
42
|
+
# R project without .Rproj file
|
|
43
|
+
project_info["type"] = "R"
|
|
44
|
+
project_info["name"] = self.working_dir.name
|
|
45
|
+
project_info["recent_files"] = self._get_recent_files([".R", ".Rmd", ".qmd"])
|
|
46
|
+
project_info["description"] = f"R project: {project_info['name']}"
|
|
47
|
+
return project_info
|
|
48
|
+
|
|
49
|
+
# Check for Python project
|
|
50
|
+
if (self.working_dir / "pyproject.toml").exists() or \
|
|
51
|
+
(self.working_dir / "setup.py").exists() or \
|
|
52
|
+
(self.working_dir / "requirements.txt").exists():
|
|
53
|
+
project_info["type"] = "Python"
|
|
54
|
+
project_info["name"] = self.working_dir.name
|
|
55
|
+
project_info["recent_files"] = self._get_recent_files([".py", ".ipynb"])
|
|
56
|
+
project_info["description"] = f"Python project: {project_info['name']}"
|
|
57
|
+
return project_info
|
|
58
|
+
|
|
59
|
+
# Check for Node.js project
|
|
60
|
+
if (self.working_dir / "package.json").exists():
|
|
61
|
+
project_info["type"] = "Node"
|
|
62
|
+
project_info["name"] = self.working_dir.name
|
|
63
|
+
project_info["recent_files"] = self._get_recent_files([".js", ".ts", ".jsx", ".tsx"])
|
|
64
|
+
project_info["description"] = f"Node.js project: {project_info['name']}"
|
|
65
|
+
return project_info
|
|
66
|
+
|
|
67
|
+
# Check for Jupyter/Data Science directory
|
|
68
|
+
ipynb_files = list(self.working_dir.glob("*.ipynb"))
|
|
69
|
+
if len(ipynb_files) >= 2: # 2+ notebooks = likely data science project
|
|
70
|
+
project_info["type"] = "Jupyter"
|
|
71
|
+
project_info["name"] = self.working_dir.name
|
|
72
|
+
project_info["recent_files"] = self._get_recent_files([".ipynb", ".py", ".csv"])
|
|
73
|
+
project_info["description"] = f"Jupyter/Data Science project: {project_info['name']}"
|
|
74
|
+
return project_info
|
|
75
|
+
|
|
76
|
+
# Check for Git repository
|
|
77
|
+
if (self.working_dir / ".git").exists():
|
|
78
|
+
project_info["type"] = "Git"
|
|
79
|
+
project_info["name"] = self.working_dir.name
|
|
80
|
+
# Get recent files of any code type
|
|
81
|
+
project_info["recent_files"] = self._get_recent_files([".py", ".js", ".R", ".java", ".cpp", ".rs"])
|
|
82
|
+
project_info["description"] = f"Git repository: {project_info['name']}"
|
|
83
|
+
return project_info
|
|
84
|
+
|
|
85
|
+
# Not in a recognized project
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
def _get_recent_files(self, extensions: List[str], limit: int = 5) -> List[Dict[str, Any]]:
|
|
89
|
+
"""Get recently modified files with given extensions"""
|
|
90
|
+
files = []
|
|
91
|
+
|
|
92
|
+
for ext in extensions:
|
|
93
|
+
for filepath in self.working_dir.glob(f"**/*{ext}"):
|
|
94
|
+
if filepath.is_file() and not any(part.startswith('.') for part in filepath.parts):
|
|
95
|
+
try:
|
|
96
|
+
mtime = filepath.stat().st_mtime
|
|
97
|
+
files.append({
|
|
98
|
+
"name": filepath.name,
|
|
99
|
+
"path": str(filepath),
|
|
100
|
+
"relative_path": str(filepath.relative_to(self.working_dir)),
|
|
101
|
+
"modified": mtime,
|
|
102
|
+
"extension": ext
|
|
103
|
+
})
|
|
104
|
+
except:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
# Sort by modification time, newest first
|
|
108
|
+
files.sort(key=lambda f: f["modified"], reverse=True)
|
|
109
|
+
return files[:limit]
|
|
110
|
+
|
|
111
|
+
def format_project_banner(self, project_info: Dict[str, Any]) -> str:
|
|
112
|
+
"""Format project info as a nice banner"""
|
|
113
|
+
if not project_info or not project_info["type"]:
|
|
114
|
+
return ""
|
|
115
|
+
|
|
116
|
+
icon_map = {
|
|
117
|
+
"R": "📊",
|
|
118
|
+
"Python": "🐍",
|
|
119
|
+
"Node": "📦",
|
|
120
|
+
"Jupyter": "📓",
|
|
121
|
+
"Git": "📂"
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
icon = icon_map.get(project_info["type"], "📁")
|
|
125
|
+
|
|
126
|
+
banner = f"\n{icon} {project_info['description']}\n"
|
|
127
|
+
|
|
128
|
+
if project_info["recent_files"]:
|
|
129
|
+
banner += "📄 Recent files:\n"
|
|
130
|
+
for f in project_info["recent_files"][:3]:
|
|
131
|
+
banner += f" • {f['relative_path']}\n"
|
|
132
|
+
|
|
133
|
+
return banner
|
|
134
|
+
|
|
135
|
+
def get_project_context_for_llm(self, project_info: Dict[str, Any]) -> str:
|
|
136
|
+
"""Get project context to add to LLM prompts"""
|
|
137
|
+
if not project_info or not project_info["type"]:
|
|
138
|
+
return ""
|
|
139
|
+
|
|
140
|
+
context = f"User is working in a {project_info['type']} project: {project_info['name']}\n"
|
|
141
|
+
|
|
142
|
+
if project_info["recent_files"]:
|
|
143
|
+
context += "Recent files:\n"
|
|
144
|
+
for f in project_info["recent_files"][:5]:
|
|
145
|
+
context += f"- {f['relative_path']}\n"
|
|
146
|
+
|
|
147
|
+
return context
|
|
148
|
+
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
cite_agent/__init__.py,sha256=wAXV2v8nNOmIAd0rh8196ItBl9hHWBVOBl5Re4VB77I,1645
|
|
2
2
|
cite_agent/__main__.py,sha256=6x3lltwG-iZHeQbN12rwvdkPDfd2Rmdk71tOOaC89Mw,179
|
|
3
|
-
cite_agent/__version__.py,sha256=
|
|
3
|
+
cite_agent/__version__.py,sha256=5ZbAQtod5QalTI1C2N07edlxplzG_Q2XvGOSyOok4uA,22
|
|
4
4
|
cite_agent/account_client.py,sha256=yLuzhIJoIZuXHXGbaVMzDxRATQwcy-wiaLnUrDuwUhI,5725
|
|
5
5
|
cite_agent/agent_backend_only.py,sha256=H4DH4hmKhT0T3rQLAb2xnnJVjxl3pOZaljL9r6JndFY,6314
|
|
6
6
|
cite_agent/ascii_plotting.py,sha256=lk8BaECs6fmjtp4iH12G09-frlRehAN7HLhHt2crers,8570
|
|
7
7
|
cite_agent/auth.py,sha256=YtoGXKwcLkZQbop37iYYL9BzRWBRPlt_D9p71VGViS4,9833
|
|
8
8
|
cite_agent/backend_only_client.py,sha256=WqLF8x7aXTro2Q3ehqKMsdCg53s6fNk9Hy86bGxqmmw,2561
|
|
9
|
-
cite_agent/cli.py,sha256=
|
|
9
|
+
cite_agent/cli.py,sha256=Qq0Gt7sNVR4R2ue10KFZElOPYrujBG9xTOqy2qetxL4,35562
|
|
10
10
|
cite_agent/cli_conversational.py,sha256=RAmgRNRyB8gQ8QLvWU-Tt23j2lmA34rQNT5F3_7SOq0,11141
|
|
11
11
|
cite_agent/cli_enhanced.py,sha256=EAaSw9qtiYRWUXF6_05T19GCXlz9cCSz6n41ASnXIPc,7407
|
|
12
12
|
cite_agent/cli_workflow.py,sha256=4oS_jW9D8ylovXbEFdsyLQONt4o0xxR4Xatfcc4tnBs,11641
|
|
13
13
|
cite_agent/dashboard.py,sha256=VGV5XQU1PnqvTsxfKMcue3j2ri_nvm9Be6O5aVays_w,10502
|
|
14
|
-
cite_agent/enhanced_ai_agent.py,sha256=
|
|
14
|
+
cite_agent/enhanced_ai_agent.py,sha256=hOL17pDKQdD1MJZRXkjEBlqyNmTdA_pcxIkQEojysFM,172282
|
|
15
|
+
cite_agent/project_detector.py,sha256=fPl5cLTy_oyufqrQ7RJ5IRVdofZoPqDRaQXW6tRtBJc,6086
|
|
15
16
|
cite_agent/rate_limiter.py,sha256=-0fXx8Tl4zVB4O28n9ojU2weRo-FBF1cJo9Z5jC2LxQ,10908
|
|
16
17
|
cite_agent/session_manager.py,sha256=B0MXSOsXdhO3DlvTG7S8x6pmGlYEDvIZ-o8TZM23niQ,9444
|
|
17
18
|
cite_agent/setup_config.py,sha256=3m2e3gw0srEWA0OygdRo64r-8HK5ohyXfct0c__CF3s,16817
|
|
@@ -22,7 +23,7 @@ cite_agent/updater.py,sha256=udoAAN4gBKAvKDV7JTh2FJO_jIhNk9bby4x6n188MEY,8458
|
|
|
22
23
|
cite_agent/web_search.py,sha256=FZCuNO7MAITiOIbpPbJyt2bzbXPzQla-9amJpnMpW_4,6520
|
|
23
24
|
cite_agent/workflow.py,sha256=a0YC0Mzz4or1C5t2gZcuJBQ0uMOZrooaI8eLu2kkI0k,15086
|
|
24
25
|
cite_agent/workflow_integration.py,sha256=A9ua0DN5pRtuU0cAwrUTGvqt2SXKhEHQbrHx16EGnDM,10910
|
|
25
|
-
cite_agent-1.3.
|
|
26
|
+
cite_agent-1.3.6.dist-info/licenses/LICENSE,sha256=XJkyO4IymhSUniN1ENY6lLrL2729gn_rbRlFK6_Hi9M,1074
|
|
26
27
|
src/__init__.py,sha256=0eEpjRfjRjOTilP66y-AbGNslBsVYr_clE-bZUzsX7s,40
|
|
27
28
|
src/services/__init__.py,sha256=pTGLCH_84mz4nGtYMwQES5w-LzoSulUtx_uuNM6r-LA,4257
|
|
28
29
|
src/services/simple_enhanced_main.py,sha256=IJoOplCqcVUg3GvN_BRyAhpGrLm_WEPy2jmHcNCY6R0,9257
|
|
@@ -49,8 +50,8 @@ src/services/research_service/synthesizer.py,sha256=lCcu37PWhWVNphHKaJJDIC-JQ5OI
|
|
|
49
50
|
src/services/search_service/__init__.py,sha256=UZFXdd7r6wietQ2kESXEyGffdfBbpghquecQde7auF4,137
|
|
50
51
|
src/services/search_service/indexer.py,sha256=u3-uwdAfmahWWsdebDF9i8XIyp7YtUMIHzlmBLBnPPM,7252
|
|
51
52
|
src/services/search_service/search_engine.py,sha256=S9HqQ_mk-8W4d4MUOgBbEGQGV29-eSuceSFvVb4Xk-k,12500
|
|
52
|
-
cite_agent-1.3.
|
|
53
|
-
cite_agent-1.3.
|
|
54
|
-
cite_agent-1.3.
|
|
55
|
-
cite_agent-1.3.
|
|
56
|
-
cite_agent-1.3.
|
|
53
|
+
cite_agent-1.3.6.dist-info/METADATA,sha256=Nw2biNkpNAmCACEe_2dJ5dGy-KvL7DtxfFuNhgNWIN4,12231
|
|
54
|
+
cite_agent-1.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
55
|
+
cite_agent-1.3.6.dist-info/entry_points.txt,sha256=bJ0u28nFIxQKH1PWQ2ak4PV-FAjhoxTC7YADEdDenFw,83
|
|
56
|
+
cite_agent-1.3.6.dist-info/top_level.txt,sha256=TgOFqJTIy8vDZuOoYA2QgagkqZtfhM5Acvt_IsWzAKo,15
|
|
57
|
+
cite_agent-1.3.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|