axel-protocol 2.3.4__tar.gz → 2.3.6__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.
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/PKG-INFO +1 -1
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/cli.py +51 -18
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/server.py +3 -1
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/static/monitor.html +5 -3
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/pyproject.toml +1 -1
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/.github/workflows/ci.yml +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/.github/workflows/publish.yml +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/.gitignore +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/CHANGELOG.md +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/CONTRIBUTING.md +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/Dockerfile +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/LICENSE +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/README.md +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/__init__.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/__init__.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/bedrock.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/cohere.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/gemini.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/groq.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/litellm.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/mistral.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/adapters/together.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/client.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/core.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/learning.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/persistence.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/testing.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/axel/universal.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/docker-compose.yml +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/docs/message-schemas.md +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/examples/demo_live.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/install.sh +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/tests/__init__.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/tests/test_adapters.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/tests/test_client.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/tests/test_core.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/tests/test_new_features.py +0 -0
- {axel_protocol-2.3.4 → axel_protocol-2.3.6}/tests/test_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: axel-protocol
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.6
|
|
4
4
|
Summary: AXEL — Agent eXchange Language: a universal protocol for multi-LLM networks
|
|
5
5
|
Project-URL: Homepage, https://github.com/sectorx/axel-protocol
|
|
6
6
|
Project-URL: Repository, https://github.com/sectorx/axel-protocol
|
|
@@ -488,14 +488,26 @@ _FREE_MODELS = [
|
|
|
488
488
|
_SPECIALIST_MODELS = {
|
|
489
489
|
"planner": "anthropic/claude-3-5-haiku", # fast, great at structured breakdown
|
|
490
490
|
"researcher": "openai/gpt-4o-mini", # strong retrieval + summarisation
|
|
491
|
-
"analyst": "google/gemini-2.0-flash-001", # quick pattern synthesis
|
|
492
|
-
"fact-checker": "mistralai/mistral-large-2411", # rigorous verification
|
|
491
|
+
"analyst": "google/gemini-2.0-flash-001", # quick pattern synthesis
|
|
492
|
+
"fact-checker": "mistralai/mistral-large-2411", # rigorous verification
|
|
493
493
|
"writer": "anthropic/claude-3-5-sonnet", # best prose quality
|
|
494
494
|
"devil-advocate": "meta-llama/llama-3.3-70b-instruct", # challenges assumptions
|
|
495
495
|
"summarizer": "qwen/qwen-2.5-72b-instruct", # distills to essence
|
|
496
496
|
"reviewer": "openai/gpt-4o", # sharpest final critic
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
+
# If a specialist model 404s or rate-limits, fall back to these automatically.
|
|
500
|
+
_FALLBACK_MODELS = {
|
|
501
|
+
"analyst": "google/gemini-flash-1.5-8b",
|
|
502
|
+
"fact-checker": "mistralai/mistral-small-3.1-24b-instruct",
|
|
503
|
+
"devil-advocate": "meta-llama/llama-3.1-70b-instruct",
|
|
504
|
+
"summarizer": "openai/gpt-4o-mini",
|
|
505
|
+
"reviewer": "openai/gpt-4o-mini",
|
|
506
|
+
"planner": "openai/gpt-4o-mini",
|
|
507
|
+
"researcher": "anthropic/claude-3-5-haiku",
|
|
508
|
+
"writer": "openai/gpt-4o-mini",
|
|
509
|
+
}
|
|
510
|
+
|
|
499
511
|
|
|
500
512
|
def _openrouter(key: str, model: str, prompt: str, timeout: int = 45) -> str:
|
|
501
513
|
"""Call OpenRouter chat completion directly. Returns response text."""
|
|
@@ -744,20 +756,41 @@ def cmd_demo(args): # noqa: C901
|
|
|
744
756
|
text = _MOCK_RESPONSES.get(action, f"[mock response for {action}]")
|
|
745
757
|
print(f" [mock] {text[:180]}{'…' if len(text) > 180 else ''}")
|
|
746
758
|
elif multi_model or single_model:
|
|
747
|
-
#
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
759
|
+
# Try specialist model, then fallback, then gpt-4o-mini as last resort
|
|
760
|
+
text = None
|
|
761
|
+
models_to_try = [mdl]
|
|
762
|
+
fallback = _FALLBACK_MODELS.get(to)
|
|
763
|
+
if fallback and fallback != mdl:
|
|
764
|
+
models_to_try.append(fallback)
|
|
765
|
+
models_to_try.append("openai/gpt-4o-mini") # always-available safety net
|
|
766
|
+
import urllib.error as _ue
|
|
767
|
+
for attempt_mdl in models_to_try:
|
|
768
|
+
attempt_short = attempt_mdl.split("/")[-1]
|
|
769
|
+
try:
|
|
770
|
+
text = _openrouter(key, attempt_mdl, full_prompt)
|
|
771
|
+
if attempt_mdl != mdl:
|
|
772
|
+
print(f" ⚠ Fell back to {attempt_short}")
|
|
773
|
+
print(f" [{to}/{attempt_short}] {text[:180]}{'…' if len(text) > 180 else ''}")
|
|
774
|
+
break
|
|
775
|
+
except _ue.HTTPError as e:
|
|
776
|
+
if e.code in (404, 429, 503):
|
|
777
|
+
print(f" ↩ {attempt_short} unavailable ({e.code}), trying next…")
|
|
778
|
+
continue
|
|
779
|
+
print(f" ❌ {to} ({attempt_short}) HTTP {e.code}")
|
|
780
|
+
break
|
|
781
|
+
except Exception as exc:
|
|
782
|
+
print(f" ❌ {to} ({attempt_short}): {exc}")
|
|
783
|
+
break
|
|
784
|
+
if text is None:
|
|
785
|
+
text = f"[{to} skipped — all models unavailable]"
|
|
786
|
+
print(f" ⚠ {to} skipped this step, pipeline continues…")
|
|
754
787
|
else:
|
|
755
788
|
try:
|
|
756
789
|
_, text = _openrouter_free(key, full_prompt, label=to)
|
|
757
790
|
except Exception as exc:
|
|
758
791
|
print(f" ❌ {to} failed: {exc}")
|
|
759
792
|
print(" Tip: run axel demo --mock to test without an API key")
|
|
760
|
-
|
|
793
|
+
text = f"[{to} skipped]"
|
|
761
794
|
_fire_result(server, to, fr, action, {"text": text[:300]})
|
|
762
795
|
if learn_key and learn_insight:
|
|
763
796
|
try:
|
|
@@ -805,7 +838,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
805
838
|
learn_insight="Breaking missions into 3 focused subtasks improves agent handoff quality",
|
|
806
839
|
mem_ctx=mem_ctx,
|
|
807
840
|
)
|
|
808
|
-
if
|
|
841
|
+
if plan is None: continue # catastrophic failure — skip run
|
|
809
842
|
|
|
810
843
|
# ── Step 2: researcher ────────────────────────────────
|
|
811
844
|
print(f"\n STEP 2/{TOTAL} Researcher investigates each subtask")
|
|
@@ -816,7 +849,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
816
849
|
learn_insight="Structured subtask research produces more complete findings",
|
|
817
850
|
mem_ctx=mem_ctx,
|
|
818
851
|
)
|
|
819
|
-
if
|
|
852
|
+
if research is None: continue
|
|
820
853
|
|
|
821
854
|
# ── Step 3: analyst ───────────────────────────────────
|
|
822
855
|
print(f"\n STEP 3/{TOTAL} Analyst synthesises the findings")
|
|
@@ -827,7 +860,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
827
860
|
learn_insight="Distilling findings to 3 insights makes downstream writing stronger",
|
|
828
861
|
mem_ctx=mem_ctx,
|
|
829
862
|
)
|
|
830
|
-
if
|
|
863
|
+
if analysis is None: continue
|
|
831
864
|
|
|
832
865
|
# ── Step 4: fact-checker ──────────────────────────────
|
|
833
866
|
print(f"\n STEP 4/{TOTAL} Fact-Checker verifies the analysis")
|
|
@@ -839,7 +872,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
839
872
|
learn_insight="Flagging unverifiable claims before writing prevents misinformation in output",
|
|
840
873
|
mem_ctx=mem_ctx,
|
|
841
874
|
)
|
|
842
|
-
if
|
|
875
|
+
if fact_check is None: continue
|
|
843
876
|
|
|
844
877
|
# ── Step 5: writer ────────────────────────────────────
|
|
845
878
|
print(f"\n STEP 5/{TOTAL} Writer drafts from verified insights")
|
|
@@ -850,7 +883,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
850
883
|
learn_insight="3-sentence summaries from verified insights land well with non-technical readers",
|
|
851
884
|
mem_ctx=mem_ctx,
|
|
852
885
|
)
|
|
853
|
-
if
|
|
886
|
+
if draft is None: continue
|
|
854
887
|
|
|
855
888
|
# ── Step 6: devil's advocate ──────────────────────────
|
|
856
889
|
print(f"\n STEP 6/{TOTAL} Devil's Advocate challenges the draft")
|
|
@@ -862,7 +895,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
862
895
|
learn_insight="Surfacing counterarguments before final review strengthens the output quality",
|
|
863
896
|
mem_ctx=mem_ctx,
|
|
864
897
|
)
|
|
865
|
-
if
|
|
898
|
+
if challenge is None: continue
|
|
866
899
|
|
|
867
900
|
# ── Step 7: summarizer ────────────────────────────────
|
|
868
901
|
print(f"\n STEP 7/{TOTAL} Summarizer distils everything to essence")
|
|
@@ -874,7 +907,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
874
907
|
learn_insight="A single-sentence TL;DR that survives counterarguments is the most durable insight",
|
|
875
908
|
mem_ctx=mem_ctx,
|
|
876
909
|
)
|
|
877
|
-
if
|
|
910
|
+
if summary is None: continue
|
|
878
911
|
|
|
879
912
|
# ── Step 8: reviewer ──────────────────────────────────
|
|
880
913
|
print(f"\n STEP 8/{TOTAL} Reviewer gives final score")
|
|
@@ -886,7 +919,7 @@ def cmd_demo(args): # noqa: C901
|
|
|
886
919
|
learn_insight="Score + strength + improvement is the most actionable review format",
|
|
887
920
|
mem_ctx=mem_ctx,
|
|
888
921
|
)
|
|
889
|
-
if
|
|
922
|
+
if review is None: continue
|
|
890
923
|
|
|
891
924
|
print("\n ─────────────────────────────────────────────────")
|
|
892
925
|
print(f" ✅ Run #{run_count} complete! ({TOTAL} tasks · {TOTAL} lessons written)")
|
|
@@ -610,7 +610,9 @@ class AXELServer:
|
|
|
610
610
|
confidence=msg.body.get("confidence", 1.0),
|
|
611
611
|
))
|
|
612
612
|
self.event_bus.publish("memory.updated", {
|
|
613
|
-
"key":
|
|
613
|
+
"key": msg.body.get("key"),
|
|
614
|
+
"insight": msg.body.get("insight", ""),
|
|
615
|
+
"source": msg.fr,
|
|
614
616
|
})
|
|
615
617
|
|
|
616
618
|
# Handle pub/sub publish messages
|
|
@@ -600,13 +600,15 @@ function onEvent(d) {
|
|
|
600
600
|
setThinking(from, false);
|
|
601
601
|
updateRateStats();
|
|
602
602
|
|
|
603
|
-
} else if (type.
|
|
603
|
+
} else if (type === 'memory.updated' || type.includes('lesson') || type.includes('learn')
|
|
604
|
+
|| (p.t === 'LS' && (p.body?.key || p.key))) {
|
|
604
605
|
const from = p.fr || p.from || p.source || '?';
|
|
605
606
|
const key = p.body?.key || p.key || '';
|
|
606
607
|
const insight = p.body?.insight || p.insight || '';
|
|
608
|
+
if (!key && !insight) return; // skip empty lesson notifications
|
|
607
609
|
agentLessons[from] = (agentLessons[from] || 0) + 1;
|
|
608
|
-
const label =
|
|
609
|
-
const detail = insight ? '"' + insight.slice(0,
|
|
610
|
+
const label = `<b>${from}</b> learned: <i>${esc(key || 'new insight')}</i>`;
|
|
611
|
+
const detail = insight ? '"' + insight.slice(0, 100) + (insight.length > 100 ? '…' : '') + '"' : '';
|
|
610
612
|
addFeed('lesson', '💡', label, detail, { rawType:'LS', from, key, fullInsight: insight });
|
|
611
613
|
pushMsg(from, `💡 ${key || 'new insight'}`);
|
|
612
614
|
pulseAgent(from, 'learning');
|
|
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
|