agentnova 0.2.3__tar.gz → 0.2.4__tar.gz
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.
- {agentnova-0.2.3 → agentnova-0.2.4}/PKG-INFO +5 -3
- {agentnova-0.2.3 → agentnova-0.2.4}/README.md +4 -2
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/__init__.py +2 -2
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/agent.py +36 -20
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/model_family_config.py +17 -12
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/15_quick_diagnostic.py +59 -4
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova.egg-info/PKG-INFO +5 -3
- {agentnova-0.2.3 → agentnova-0.2.4}/pyproject.toml +1 -1
- {agentnova-0.2.3 → agentnova-0.2.4}/LICENSE +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/__main__.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/acp_plugin.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/agent_mode.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/bitnet_client.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/bitnet_setup.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/cli.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/config.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/math_prompts.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/memory.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/ollama_client.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/orchestrator.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/orchestrator_enhanced.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/core/tools.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/00_backend_demo.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/01_basic_agent.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/02_tool_agent.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/03_orchestrator.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/04_comprehensive_test.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/05_tool_tests.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/06_interactive_chat.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/07_model_comparison.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/08_robust_comparison.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/09_expanded_benchmark.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/10_skills_demo.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/11_skill_creator_test.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/12_batch_operations.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/13_shutdown_demo.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/examples/14_gsm8k_benchmark.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/model_discovery.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/shared_args.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/__init__.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/acp/SKILL.md +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/datetime/SKILL.md +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/loader.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/SKILL.md +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/__init__.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/aggregate_benchmark.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/generate_report.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/improve_description.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/init_skill.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/package_skill.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/quick_validate.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/run_eval.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/run_loop.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/security_scan.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/test_package_skill.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/test_quick_validate.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/utils.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/validate.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/web_search/SKILL.md +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/tools/builtins.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova/tools/sandboxed_repl.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova.egg-info/SOURCES.txt +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova.egg-info/dependency_links.txt +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova.egg-info/entry_points.txt +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova.egg-info/requires.txt +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/agentnova.egg-info/top_level.txt +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/localclaw/__init__.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/localclaw/__main__.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/setup.cfg +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/tests/test_acp_integration.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/tests/test_acp_subagents.py +0 -0
- {agentnova-0.2.3 → agentnova-0.2.4}/tests/test_agent.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentnova
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: A minimal, hackable agentic framework for Ollama and BitNet - local-first AI agent toolkit
|
|
5
5
|
Author-email: VTSTech <veritas@vts-tech.org>
|
|
6
6
|
Maintainer-email: VTSTech <veritas@vts-tech.org>
|
|
@@ -34,7 +34,7 @@ Requires-Dist: black>=23.0; extra == "dev"
|
|
|
34
34
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
35
35
|
Dynamic: license-file
|
|
36
36
|
|
|
37
|
-
# ⚛️ AgentNova R02.
|
|
37
|
+
# ⚛️ AgentNova R02.4
|
|
38
38
|
|
|
39
39
|
A minimal, hackable agentic framework engineered to run **entirely locally** with [Ollama](https://ollama.com) or [BitNet](https://github.com/microsoft/BitNet).
|
|
40
40
|
|
|
@@ -44,7 +44,9 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
44
44
|
|
|
45
45
|
[](https://colab.research.google.com/github/VTSTech/AgentNova/blob/main/AgentNova.ipynb)
|
|
46
46
|
[](https://GitHub.com/VTSTech/AgentNova/commit/) [](https://GitHub.com/VTSTech/AgentNova/commit/)
|
|
47
|
-
|
|
47
|
+
|
|
48
|
+
[](https://pypi.org/project/agentnova/) [](https://pypi.python.org/pypi/agentnova/) [](https://pypi.python.org/pypi/agentnova/) [](https://pypi.python.org/pypi/agentnova/)
|
|
49
|
+
|
|
48
50
|
[](#license) [](https://python.org)
|
|
49
51
|
|
|
50
52
|
---
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ⚛️ AgentNova R02.
|
|
1
|
+
# ⚛️ AgentNova R02.4
|
|
2
2
|
|
|
3
3
|
A minimal, hackable agentic framework engineered to run **entirely locally** with [Ollama](https://ollama.com) or [BitNet](https://github.com/microsoft/BitNet).
|
|
4
4
|
|
|
@@ -8,7 +8,9 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
8
8
|
|
|
9
9
|
[](https://colab.research.google.com/github/VTSTech/AgentNova/blob/main/AgentNova.ipynb)
|
|
10
10
|
[](https://GitHub.com/VTSTech/AgentNova/commit/) [](https://GitHub.com/VTSTech/AgentNova/commit/)
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
[](https://pypi.org/project/agentnova/) [](https://pypi.python.org/pypi/agentnova/) [](https://pypi.python.org/pypi/agentnova/) [](https://pypi.python.org/pypi/agentnova/)
|
|
13
|
+
|
|
12
14
|
[](#license) [](https://python.org)
|
|
13
15
|
|
|
14
16
|
---
|
|
@@ -204,8 +204,8 @@ __all__ = [
|
|
|
204
204
|
if _BITNET_AVAILABLE:
|
|
205
205
|
__all__.extend(["BitnetClient", "KNOWN_MODELS"])
|
|
206
206
|
|
|
207
|
-
__version__ = "0.2.
|
|
207
|
+
__version__ = "0.2.4"
|
|
208
208
|
__author__ = "VTSTech"
|
|
209
|
-
__author_email__ = "
|
|
209
|
+
__author_email__ = "veritas@vts-tech.org"
|
|
210
210
|
__url__ = "https://github.com/VTSTech/AgentNova"
|
|
211
211
|
__website__ = "https://www.vts-tech.org"
|
|
@@ -1847,7 +1847,9 @@ class Agent:
|
|
|
1847
1847
|
# ── Immediate synthesize after successful tool result ───────────── #
|
|
1848
1848
|
# Prevents small models re-invoking tools when the answer is in hand.
|
|
1849
1849
|
# Triggered when: a tool succeeded AND the query is simple (date, math, etc.)
|
|
1850
|
-
|
|
1850
|
+
# NOTE: Skip for ReAct mode - ReAct has its own "Final Answer" mechanism
|
|
1851
|
+
# that we need to respect (model may output "Final Answer: X" after tools)
|
|
1852
|
+
if _successful_results and _is_simple_answered_query(user_input, _successful_results) and self._native_tools:
|
|
1851
1853
|
final_answer = self._synthesize(user_input, _successful_results)
|
|
1852
1854
|
final_step = StepResult(type="final", content=final_answer, elapsed_ms=elapsed)
|
|
1853
1855
|
run.steps.append(final_step)
|
|
@@ -2558,6 +2560,21 @@ class Agent:
|
|
|
2558
2560
|
else:
|
|
2559
2561
|
fallback_text = content
|
|
2560
2562
|
|
|
2563
|
+
# For ReAct mode: if model output looks incomplete (just "Thought: ..." without Final Answer)
|
|
2564
|
+
# and we have a numeric result, use the numeric result directly
|
|
2565
|
+
if not self._native_tools and _successful_results:
|
|
2566
|
+
content_stripped = content.strip()
|
|
2567
|
+
# Check if content is just a thought without actual answer
|
|
2568
|
+
if content_stripped.startswith("Thought:") and "Final Answer:" not in content_stripped:
|
|
2569
|
+
# Try to use numeric fallback
|
|
2570
|
+
try:
|
|
2571
|
+
fallback_num = float(fallback_text)
|
|
2572
|
+
if self.debug:
|
|
2573
|
+
print(f"\n 🔍 DEBUG: ReAct thought without Final Answer, using numeric result: {fallback_num}")
|
|
2574
|
+
content = fallback_text
|
|
2575
|
+
except (ValueError, TypeError):
|
|
2576
|
+
pass # Fall through to normal processing
|
|
2577
|
+
|
|
2561
2578
|
if self.debug:
|
|
2562
2579
|
print(f"\n 🔍 DEBUG: Final answer processing")
|
|
2563
2580
|
print(f" content (before clean)={content!r}")
|
|
@@ -2594,25 +2611,24 @@ class Agent:
|
|
|
2594
2611
|
return "I was unable to complete this task with the available tools."
|
|
2595
2612
|
|
|
2596
2613
|
results_text = "\n".join(f"- {r}" for r in results)
|
|
2597
|
-
|
|
2598
|
-
# For
|
|
2599
|
-
#
|
|
2600
|
-
if
|
|
2601
|
-
|
|
2614
|
+
|
|
2615
|
+
# For numeric results, use the LAST one directly without LLM synthesis
|
|
2616
|
+
# NOTE: We no longer try to detect incomplete multi-step calculations
|
|
2617
|
+
# because we can't tell if the model computed the full expression or not
|
|
2618
|
+
# (e.g., "8 * 7 - 5" vs just "8 * 7"). Returning the numeric result directly
|
|
2619
|
+
# is safer than forcing LLM synthesis which might hallucinate.
|
|
2620
|
+
r_clean = _strip_tool_prefix(results[-1])
|
|
2621
|
+
if self.debug:
|
|
2622
|
+
print(f" synthesize: checking if numeric: '{r_clean}'")
|
|
2623
|
+
try:
|
|
2624
|
+
num = float(r_clean)
|
|
2602
2625
|
if self.debug:
|
|
2603
|
-
print(f" synthesize:
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
print(f" synthesize: using numeric result directly: {num}")
|
|
2610
|
-
# Return just the number as string - test expects this
|
|
2611
|
-
return r_clean
|
|
2612
|
-
except (ValueError, TypeError) as e:
|
|
2613
|
-
if self.debug:
|
|
2614
|
-
print(f" synthesize: not numeric: {e}")
|
|
2615
|
-
pass
|
|
2626
|
+
print(f" synthesize: using numeric result directly: {num}")
|
|
2627
|
+
return r_clean
|
|
2628
|
+
except (ValueError, TypeError):
|
|
2629
|
+
if self.debug:
|
|
2630
|
+
print(f" synthesize: not numeric: could not convert string to float: '{r_clean}'")
|
|
2631
|
+
pass
|
|
2616
2632
|
|
|
2617
2633
|
# Check if any result already looks like a complete answer
|
|
2618
2634
|
# (starts with common answer patterns and is reasonably short)
|
|
@@ -2632,7 +2648,7 @@ class Agent:
|
|
|
2632
2648
|
|
|
2633
2649
|
if self.debug:
|
|
2634
2650
|
print(f" synthesize: making LLM call to summarize {len(results)} results...")
|
|
2635
|
-
|
|
2651
|
+
|
|
2636
2652
|
# For synthesis, don't include the model's potentially wrong pre-tool responses
|
|
2637
2653
|
# Just use the system prompt and the synthesis request
|
|
2638
2654
|
synthesis_messages = [
|
|
@@ -226,23 +226,28 @@ Answer: 8""",
|
|
|
226
226
|
few_shot_style="compact",
|
|
227
227
|
reasoning_hints=["Be direct and helpful", "Follow instructions precisely"],
|
|
228
228
|
# Optimized prompt for pure reasoning (Dolphin has no tool support)
|
|
229
|
-
no_tools_system_prompt="""You are Dolphin, a helpful AI assistant.
|
|
229
|
+
no_tools_system_prompt="""You are Dolphin, a helpful AI assistant.
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
Be concise and direct. For math, show the calculation then the answer.
|
|
232
232
|
|
|
233
233
|
Examples:
|
|
234
|
-
|
|
235
|
-
15 + 27 = 42
|
|
236
|
-
Answer: 42
|
|
234
|
+
Q: What is 15 plus 27?
|
|
235
|
+
A: 15 + 27 = 42
|
|
237
236
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
56 - 5 = 51
|
|
241
|
-
Answer: 51
|
|
237
|
+
Q: What is 17 divided by 4?
|
|
238
|
+
A: 17 / 4 = 4.25
|
|
242
239
|
|
|
243
|
-
|
|
244
|
-
24 - 8 - 6 = 10
|
|
245
|
-
|
|
240
|
+
Q: A store has 24 apples. They sell 8 and 6. How many left?
|
|
241
|
+
A: 24 - 8 - 6 = 10
|
|
242
|
+
|
|
243
|
+
Q: A store opens at 9 AM and closes at 5 PM. How many hours?
|
|
244
|
+
A: 17 - 9 = 8 hours
|
|
245
|
+
|
|
246
|
+
Q: What is the capital of Japan?
|
|
247
|
+
A: Tokyo
|
|
248
|
+
|
|
249
|
+
Q: Is 15 greater than 10?
|
|
250
|
+
A: Yes""",
|
|
246
251
|
),
|
|
247
252
|
}
|
|
248
253
|
|
|
@@ -48,6 +48,15 @@ config = parse_shared_args(args)
|
|
|
48
48
|
|
|
49
49
|
DEBUG = config.debug
|
|
50
50
|
|
|
51
|
+
# Check for optional ACP support
|
|
52
|
+
USE_ACP = config.acp
|
|
53
|
+
if USE_ACP:
|
|
54
|
+
try:
|
|
55
|
+
from agentnova.acp_plugin import ACPPlugin
|
|
56
|
+
except ImportError:
|
|
57
|
+
print("⚠️ ACP requested but ACPPlugin not available")
|
|
58
|
+
USE_ACP = False
|
|
59
|
+
|
|
51
60
|
# Quick 5-question diagnostic test
|
|
52
61
|
# Each question targets a specific failure mode
|
|
53
62
|
TESTS = [
|
|
@@ -101,7 +110,7 @@ def make_step_callback(verbose: bool = True):
|
|
|
101
110
|
return on_step
|
|
102
111
|
|
|
103
112
|
|
|
104
|
-
def test_model(client, model: str, config: SharedConfig) -> dict:
|
|
113
|
+
def test_model(client, model: str, config: SharedConfig, acp=None) -> dict:
|
|
105
114
|
"""Test a single model and return results."""
|
|
106
115
|
print(f"\n{'='*60}")
|
|
107
116
|
print(f"🧪 Quick Diagnostic: {model}")
|
|
@@ -109,6 +118,10 @@ def test_model(client, model: str, config: SharedConfig) -> dict:
|
|
|
109
118
|
|
|
110
119
|
results = {"model": model, "passed": 0, "total": len(TESTS), "time": 0, "tests": {}}
|
|
111
120
|
|
|
121
|
+
# Log test start to ACP
|
|
122
|
+
if acp:
|
|
123
|
+
acp.log_chat("system", f"Quick Diagnostic started for {model}", complete=True)
|
|
124
|
+
|
|
112
125
|
for i, (test_name, prompt, tools, expected) in enumerate(TESTS):
|
|
113
126
|
print(f" {test_name}...", end=" ", flush=True)
|
|
114
127
|
|
|
@@ -137,7 +150,7 @@ After getting the result, provide the final answer as a number."""
|
|
|
137
150
|
max_steps=5,
|
|
138
151
|
client=fresh_client,
|
|
139
152
|
model_options=model_opts,
|
|
140
|
-
force_react=(tool_support == "react"),
|
|
153
|
+
force_react=config.force_react or (tool_support == "react"),
|
|
141
154
|
on_step=make_step_callback(DEBUG),
|
|
142
155
|
debug=DEBUG,
|
|
143
156
|
)
|
|
@@ -178,10 +191,20 @@ After getting the result, provide the final answer as a number."""
|
|
|
178
191
|
else:
|
|
179
192
|
print(f"❌ ({elapsed:.1f}s)")
|
|
180
193
|
print(f" Expected: {expected}, Got: {response[:80]}")
|
|
194
|
+
|
|
195
|
+
# Log to ACP
|
|
196
|
+
if acp:
|
|
197
|
+
acp.log_chat(
|
|
198
|
+
"assistant" if passed else "error",
|
|
199
|
+
f"{test_name}: {'PASS' if passed else 'FAIL'} - Expected: {expected}, Got: {response[:50]}",
|
|
200
|
+
complete=True
|
|
201
|
+
)
|
|
181
202
|
|
|
182
203
|
except Exception as e:
|
|
183
204
|
results["tests"][test_name] = {"passed": False, "error": str(e)[:100]}
|
|
184
205
|
print(f"❌ ERROR: {str(e)[:50]}")
|
|
206
|
+
if acp:
|
|
207
|
+
acp.log_chat("error", f"{test_name}: ERROR - {str(e)[:50]}", complete=True)
|
|
185
208
|
|
|
186
209
|
pass_rate = results["passed"] / results["total"] * 100
|
|
187
210
|
print(f"\n 📊 Result: {results['passed']}/{results['total']} ({pass_rate:.0f}%) in {results['time']:.1f}s")
|
|
@@ -199,8 +222,22 @@ def main():
|
|
|
199
222
|
from agentnova.model_discovery import get_available_models
|
|
200
223
|
available = list(dict.fromkeys(get_available_models(client)))
|
|
201
224
|
|
|
225
|
+
# Create main ACP instance if enabled
|
|
226
|
+
main_acp = None
|
|
227
|
+
acp_connected = False
|
|
228
|
+
if USE_ACP:
|
|
229
|
+
main_acp = ACPPlugin(
|
|
230
|
+
agent_name="AgentNova",
|
|
231
|
+
model_name="quick-diagnostic",
|
|
232
|
+
debug=DEBUG,
|
|
233
|
+
)
|
|
234
|
+
bootstrap = main_acp.bootstrap(claim_primary=False)
|
|
235
|
+
acp_connected = bootstrap.get("status") is not None
|
|
236
|
+
|
|
202
237
|
print(f"\n⚛️ AgentNova Quick Diagnostic (5 questions)")
|
|
203
238
|
print(f" Available models: {', '.join(available[:5])}{'...' if len(available) > 5 else ''}")
|
|
239
|
+
if USE_ACP:
|
|
240
|
+
print(f" ACP: {'connected' if acp_connected else 'unavailable'}")
|
|
204
241
|
|
|
205
242
|
# Determine which models to test
|
|
206
243
|
if config.model:
|
|
@@ -222,7 +259,17 @@ def main():
|
|
|
222
259
|
|
|
223
260
|
all_results = []
|
|
224
261
|
for model in models_to_test:
|
|
225
|
-
|
|
262
|
+
# Create model-specific ACP instance if enabled
|
|
263
|
+
model_acp = None
|
|
264
|
+
if USE_ACP and acp_connected:
|
|
265
|
+
model_acp = ACPPlugin(
|
|
266
|
+
agent_name="AgentNova",
|
|
267
|
+
model_name=model.split(':')[0][:25],
|
|
268
|
+
debug=DEBUG,
|
|
269
|
+
)
|
|
270
|
+
model_acp.bootstrap(claim_primary=False)
|
|
271
|
+
|
|
272
|
+
result = test_model(client, model, config, acp=model_acp)
|
|
226
273
|
all_results.append(result)
|
|
227
274
|
|
|
228
275
|
# Summary
|
|
@@ -231,10 +278,18 @@ def main():
|
|
|
231
278
|
print("🏆 RANKINGS")
|
|
232
279
|
print(f"{'='*60}")
|
|
233
280
|
sorted_results = sorted(all_results, key=lambda x: (-x["passed"], x["time"]))
|
|
281
|
+
summary_lines = []
|
|
234
282
|
for i, r in enumerate(sorted_results, 1):
|
|
235
283
|
medal = "🥇" if i == 1 else "🥈" if i == 2 else "🥉" if i == 3 else " "
|
|
236
284
|
rate = r["passed"] / r["total"] * 100
|
|
237
|
-
|
|
285
|
+
line = f"{medal} {r['model']:<35} {r['passed']}/{r['total']} ({rate:.0f}%) - {r['time']:.1f}s"
|
|
286
|
+
print(line)
|
|
287
|
+
summary_lines.append(f"{r['model']}: {r['passed']}/{r['total']} ({rate:.0f}%)")
|
|
288
|
+
|
|
289
|
+
# Log summary to ACP
|
|
290
|
+
if main_acp and acp_connected:
|
|
291
|
+
summary_text = "Quick Diagnostic Rankings:\n" + "\n".join(summary_lines)
|
|
292
|
+
main_acp.log_chat("system", summary_text, complete=True)
|
|
238
293
|
|
|
239
294
|
|
|
240
295
|
if __name__ == "__main__":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentnova
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: A minimal, hackable agentic framework for Ollama and BitNet - local-first AI agent toolkit
|
|
5
5
|
Author-email: VTSTech <veritas@vts-tech.org>
|
|
6
6
|
Maintainer-email: VTSTech <veritas@vts-tech.org>
|
|
@@ -34,7 +34,7 @@ Requires-Dist: black>=23.0; extra == "dev"
|
|
|
34
34
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
35
35
|
Dynamic: license-file
|
|
36
36
|
|
|
37
|
-
# ⚛️ AgentNova R02.
|
|
37
|
+
# ⚛️ AgentNova R02.4
|
|
38
38
|
|
|
39
39
|
A minimal, hackable agentic framework engineered to run **entirely locally** with [Ollama](https://ollama.com) or [BitNet](https://github.com/microsoft/BitNet).
|
|
40
40
|
|
|
@@ -44,7 +44,9 @@ Inspired by the architecture of OpenClaw, rebuilt from scratch for local-first o
|
|
|
44
44
|
|
|
45
45
|
[](https://colab.research.google.com/github/VTSTech/AgentNova/blob/main/AgentNova.ipynb)
|
|
46
46
|
[](https://GitHub.com/VTSTech/AgentNova/commit/) [](https://GitHub.com/VTSTech/AgentNova/commit/)
|
|
47
|
-
|
|
47
|
+
|
|
48
|
+
[](https://pypi.org/project/agentnova/) [](https://pypi.python.org/pypi/agentnova/) [](https://pypi.python.org/pypi/agentnova/) [](https://pypi.python.org/pypi/agentnova/)
|
|
49
|
+
|
|
48
50
|
[](#license) [](https://python.org)
|
|
49
51
|
|
|
50
52
|
---
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentnova"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "A minimal, hackable agentic framework for Ollama and BitNet - local-first AI agent toolkit"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/aggregate_benchmark.py
RENAMED
|
File without changes
|
{agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/generate_report.py
RENAMED
|
File without changes
|
{agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/improve_description.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/quick_validate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/test_package_skill.py
RENAMED
|
File without changes
|
{agentnova-0.2.3 → agentnova-0.2.4}/agentnova/skills/skill-creator/scripts/test_quick_validate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|