fahali 0.1.0__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.
- fahali-0.1.0/PKG-INFO +117 -0
- fahali-0.1.0/README.md +100 -0
- fahali-0.1.0/fahali/__init__.py +128 -0
- fahali-0.1.0/fahali/crewai.py +36 -0
- fahali-0.1.0/fahali/langchain.py +22 -0
- fahali-0.1.0/fahali/llamaindex.py +19 -0
- fahali-0.1.0/pyproject.toml +24 -0
fahali-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fahali
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Market intelligence AI agents can verify - signed receipts, judged track record (misses included), Brier-calibrated forecasts. Adapters for LangChain, CrewAI, LlamaIndex, AutoGen, smolagents. MCP: mcp.fahaliai.com
|
|
5
|
+
Project-URL: Homepage, https://fahaliai.com/developer
|
|
6
|
+
Project-URL: Documentation, https://fahaliai.com/developer
|
|
7
|
+
Project-URL: Repository, https://github.com/BobMain-2025/fahali-integrations
|
|
8
|
+
Author-email: Future Legends AI <robert@futurelegendsai.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: ai-agents,crewai,crypto,function-calling,langchain,llamaindex,market-intelligence,mcp,risk
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# fahali
|
|
19
|
+
|
|
20
|
+
**Market intelligence AI agents can verify.** Every verdict carries a signed SHA-256 receipt. Every judged signal has a public replay URL. The track record keeps its misses and publishes its methodology. Forecast probabilities are Brier-scored against realized outcomes.
|
|
21
|
+
|
|
22
|
+
Zero dependencies. Works with any agent framework. *Observation, not advice.*
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install fahali # Python
|
|
26
|
+
npm install fahali # JS/TS
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Free key (50 calls/day, no card): [app.fahaliai.com/developer](https://app.fahaliai.com/developer) · Docs: [fahaliai.com/developer](https://fahaliai.com/developer) · MCP: `https://mcp.fahaliai.com/mcp`
|
|
30
|
+
|
|
31
|
+
## Direct
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { FahaliClient } from "fahali";
|
|
35
|
+
|
|
36
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
37
|
+
const verdict = await fahali.verdict(["BTCUSDT"]); // committee read + signed receipt
|
|
38
|
+
const record = await fahali.symbolRecord("BTCUSDT"); // judged record, misses included
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## OpenAI (and anything using function-calling format)
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { FahaliClient, FAHALI_TOOLS, executeTool } from "fahali";
|
|
45
|
+
|
|
46
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
47
|
+
const tools = FAHALI_TOOLS.map((t) => ({ type: "function", function: t }));
|
|
48
|
+
// ...pass `tools` to chat.completions.create; on a tool call:
|
|
49
|
+
const result = await executeTool(fahali, call.function.name, JSON.parse(call.function.arguments));
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## LangChain (Python)
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from fahali import FahaliClient
|
|
56
|
+
from fahali.langchain import get_langchain_tools
|
|
57
|
+
tools = get_langchain_tools(FahaliClient(api_key=...))
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## CrewAI
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from fahali.crewai import get_crewai_tools
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## LlamaIndex
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from fahali.llamaindex import get_llamaindex_tools
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## AutoGen / smolagents / Semantic Kernel / raw OpenAI
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from fahali import FahaliClient, TOOL_SPECS, execute_tool # function-calling format
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Vercel AI SDK
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { tool, jsonSchema, generateText } from "ai";
|
|
82
|
+
import { FahaliClient, toAiSdkTools } from "fahali";
|
|
83
|
+
|
|
84
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
85
|
+
const { text } = await generateText({
|
|
86
|
+
model,
|
|
87
|
+
tools: toAiSdkTools(fahali, { tool, jsonSchema }),
|
|
88
|
+
prompt: "Is anything threatening a BTC-heavy portfolio right now? Cite replays.",
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## LangChain.js
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
96
|
+
import { FahaliClient, toLangchainTools } from "fahali";
|
|
97
|
+
|
|
98
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
99
|
+
const tools = toLangchainTools(fahali, { DynamicStructuredTool });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Tools
|
|
103
|
+
|
|
104
|
+
| Tool | What your agent gets |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `fahali_verdict` | 18-engine committee read: agreement, dissent on the record, signed receipt, replay URL |
|
|
107
|
+
| `fahali_forecast_72h` | Crash/neutral/pump distribution, Brier-calibrated |
|
|
108
|
+
| `fahali_tape` | Latest judged calls market-wide — hits **and misses** |
|
|
109
|
+
| `fahali_symbol_record` | Per-symbol judged record with replay URLs |
|
|
110
|
+
| `fahali_track_record` | Aggregate scorecard: lift vs base rate, sample sizes, disclosed gaps |
|
|
111
|
+
| `fahali_recent_alerts` | Live detections across ~600 scanned instruments |
|
|
112
|
+
|
|
113
|
+
## Why this instead of a terminal or search
|
|
114
|
+
|
|
115
|
+
Terminals were built for human eyes; search gives agents unaccountable text. Fahali's answers are **claims your agent can check**: methodology at [fahaliai.com/methodology](https://fahaliai.com/methodology), pricing free → metered at [fahaliai.com/developer](https://fahaliai.com/developer).
|
|
116
|
+
|
|
117
|
+
MIT © Future Legends AI. Nothing here is a recommendation to buy or sell anything.
|
fahali-0.1.0/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# fahali
|
|
2
|
+
|
|
3
|
+
**Market intelligence AI agents can verify.** Every verdict carries a signed SHA-256 receipt. Every judged signal has a public replay URL. The track record keeps its misses and publishes its methodology. Forecast probabilities are Brier-scored against realized outcomes.
|
|
4
|
+
|
|
5
|
+
Zero dependencies. Works with any agent framework. *Observation, not advice.*
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install fahali # Python
|
|
9
|
+
npm install fahali # JS/TS
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Free key (50 calls/day, no card): [app.fahaliai.com/developer](https://app.fahaliai.com/developer) · Docs: [fahaliai.com/developer](https://fahaliai.com/developer) · MCP: `https://mcp.fahaliai.com/mcp`
|
|
13
|
+
|
|
14
|
+
## Direct
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { FahaliClient } from "fahali";
|
|
18
|
+
|
|
19
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
20
|
+
const verdict = await fahali.verdict(["BTCUSDT"]); // committee read + signed receipt
|
|
21
|
+
const record = await fahali.symbolRecord("BTCUSDT"); // judged record, misses included
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## OpenAI (and anything using function-calling format)
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { FahaliClient, FAHALI_TOOLS, executeTool } from "fahali";
|
|
28
|
+
|
|
29
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
30
|
+
const tools = FAHALI_TOOLS.map((t) => ({ type: "function", function: t }));
|
|
31
|
+
// ...pass `tools` to chat.completions.create; on a tool call:
|
|
32
|
+
const result = await executeTool(fahali, call.function.name, JSON.parse(call.function.arguments));
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## LangChain (Python)
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from fahali import FahaliClient
|
|
39
|
+
from fahali.langchain import get_langchain_tools
|
|
40
|
+
tools = get_langchain_tools(FahaliClient(api_key=...))
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## CrewAI
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from fahali.crewai import get_crewai_tools
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## LlamaIndex
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from fahali.llamaindex import get_llamaindex_tools
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## AutoGen / smolagents / Semantic Kernel / raw OpenAI
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from fahali import FahaliClient, TOOL_SPECS, execute_tool # function-calling format
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Vercel AI SDK
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { tool, jsonSchema, generateText } from "ai";
|
|
65
|
+
import { FahaliClient, toAiSdkTools } from "fahali";
|
|
66
|
+
|
|
67
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
68
|
+
const { text } = await generateText({
|
|
69
|
+
model,
|
|
70
|
+
tools: toAiSdkTools(fahali, { tool, jsonSchema }),
|
|
71
|
+
prompt: "Is anything threatening a BTC-heavy portfolio right now? Cite replays.",
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## LangChain.js
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
79
|
+
import { FahaliClient, toLangchainTools } from "fahali";
|
|
80
|
+
|
|
81
|
+
const fahali = new FahaliClient({ apiKey: process.env.FAHALI_API_KEY });
|
|
82
|
+
const tools = toLangchainTools(fahali, { DynamicStructuredTool });
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Tools
|
|
86
|
+
|
|
87
|
+
| Tool | What your agent gets |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `fahali_verdict` | 18-engine committee read: agreement, dissent on the record, signed receipt, replay URL |
|
|
90
|
+
| `fahali_forecast_72h` | Crash/neutral/pump distribution, Brier-calibrated |
|
|
91
|
+
| `fahali_tape` | Latest judged calls market-wide — hits **and misses** |
|
|
92
|
+
| `fahali_symbol_record` | Per-symbol judged record with replay URLs |
|
|
93
|
+
| `fahali_track_record` | Aggregate scorecard: lift vs base rate, sample sizes, disclosed gaps |
|
|
94
|
+
| `fahali_recent_alerts` | Live detections across ~600 scanned instruments |
|
|
95
|
+
|
|
96
|
+
## Why this instead of a terminal or search
|
|
97
|
+
|
|
98
|
+
Terminals were built for human eyes; search gives agents unaccountable text. Fahali's answers are **claims your agent can check**: methodology at [fahaliai.com/methodology](https://fahaliai.com/methodology), pricing free → metered at [fahaliai.com/developer](https://fahaliai.com/developer).
|
|
99
|
+
|
|
100
|
+
MIT © Future Legends AI. Nothing here is a recommendation to buy or sell anything.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""fahali — market intelligence AI agents can verify.
|
|
2
|
+
|
|
3
|
+
Signed receipts on every verdict, a judged track record that keeps its
|
|
4
|
+
misses, Brier-calibrated forecasts, public replays. Observation, not advice.
|
|
5
|
+
|
|
6
|
+
Free key (50 calls/day): https://app.fahaliai.com/developer
|
|
7
|
+
Adapters: fahali.langchain, fahali.crewai, fahali.llamaindex — plus
|
|
8
|
+
TOOL_SPECS (OpenAI function-calling format) for AutoGen, smolagents,
|
|
9
|
+
Semantic Kernel, or anything else.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import urllib.request
|
|
15
|
+
import urllib.error
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
__version__ = "0.1.0"
|
|
19
|
+
DEFAULT_BASE_URL = "https://app.fahaliai.com"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class FahaliError(RuntimeError):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class FahaliClient:
|
|
27
|
+
"""Minimal, dependency-free client for the Fahali API."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, api_key: Optional[str] = None, base_url: str = DEFAULT_BASE_URL, timeout: float = 20.0):
|
|
30
|
+
self.api_key = api_key
|
|
31
|
+
self.base_url = base_url.rstrip("/")
|
|
32
|
+
self.timeout = timeout
|
|
33
|
+
|
|
34
|
+
def _get(self, path: str) -> Any:
|
|
35
|
+
req = urllib.request.Request(self.base_url + path)
|
|
36
|
+
if self.api_key:
|
|
37
|
+
req.add_header("Authorization", f"Bearer {self.api_key}")
|
|
38
|
+
try:
|
|
39
|
+
with urllib.request.urlopen(req, timeout=self.timeout) as r:
|
|
40
|
+
return json.loads(r.read().decode("utf-8"))
|
|
41
|
+
except urllib.error.HTTPError as e:
|
|
42
|
+
body = e.read().decode("utf-8", "ignore")[:300]
|
|
43
|
+
raise FahaliError(f"Fahali {e.code} on {path}: {body}") from None
|
|
44
|
+
|
|
45
|
+
def verdict(self, symbols: list[str]) -> Any:
|
|
46
|
+
"""Committee verdict(s) with signed receipts."""
|
|
47
|
+
return self._get(f"/api/agent/verdict?symbols={','.join(symbols)}")
|
|
48
|
+
|
|
49
|
+
def forecast_72h(self, symbol: str) -> Any:
|
|
50
|
+
"""72h crash/neutral/pump forecast (Brier-calibrated distribution)."""
|
|
51
|
+
return self._get(f"/api/forecast/72h?symbol={symbol}")
|
|
52
|
+
|
|
53
|
+
def tape(self) -> Any:
|
|
54
|
+
"""Latest judged calls market-wide — hits AND misses. Public."""
|
|
55
|
+
return self._get("/api/tape")
|
|
56
|
+
|
|
57
|
+
def replay(self, signal_id: str) -> Any:
|
|
58
|
+
"""Public replay of one judged signal — citable proof."""
|
|
59
|
+
return self._get(f"/api/replay/{signal_id}")
|
|
60
|
+
|
|
61
|
+
def symbol_record(self, symbol: str) -> Any:
|
|
62
|
+
"""Per-symbol judged record (last 9 calls, misses included). Public."""
|
|
63
|
+
return self._get(f"/api/replay/history/{symbol}")
|
|
64
|
+
|
|
65
|
+
def track_record(self) -> Any:
|
|
66
|
+
"""Aggregate scorecard: lift vs base rates, samples, disclosed gaps."""
|
|
67
|
+
return self._get("/api/track-record/scorecard")
|
|
68
|
+
|
|
69
|
+
def recent_alerts(self) -> Any:
|
|
70
|
+
"""Latest detections across the scanned universe."""
|
|
71
|
+
return self._get("/api/alerts/recent")
|
|
72
|
+
|
|
73
|
+
def public_stats(self) -> Any:
|
|
74
|
+
"""Coverage + freshness. Public, no auth."""
|
|
75
|
+
return self._get("/api/public/stats")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# OpenAI function-calling format — AutoGen, Semantic Kernel, raw OpenAI, etc.
|
|
79
|
+
TOOL_SPECS: list[dict[str, Any]] = [
|
|
80
|
+
{
|
|
81
|
+
"name": "fahali_verdict",
|
|
82
|
+
"description": "Committee market verdict for symbols (e.g. BTCUSDT). 18 engines vote; includes agreement, dissent kept on the record, a signed SHA-256 receipt and a public replay URL. Observation, not advice.",
|
|
83
|
+
"parameters": {"type": "object", "properties": {"symbols": {"type": "array", "items": {"type": "string"}}}, "required": ["symbols"]},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "fahali_forecast_72h",
|
|
87
|
+
"description": "72-hour crash/neutral/pump probability forecast for one symbol; the distribution is Brier-scored against realized outcomes.",
|
|
88
|
+
"parameters": {"type": "object", "properties": {"symbol": {"type": "string"}}, "required": ["symbol"]},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"name": "fahali_tape",
|
|
92
|
+
"description": "The live tape: latest judged calls across the market, hits AND misses, each with a public replay URL.",
|
|
93
|
+
"parameters": {"type": "object", "properties": {}},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "fahali_symbol_record",
|
|
97
|
+
"description": "Judged track record for one symbol: last 9 calls with hit/miss outcomes and replay URLs.",
|
|
98
|
+
"parameters": {"type": "object", "properties": {"symbol": {"type": "string"}}, "required": ["symbol"]},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "fahali_track_record",
|
|
102
|
+
"description": "Aggregate scorecard: directional/magnitude/forecast axes with sample sizes and disclosed gap windows. Read lift vs base rate, never raw percentages.",
|
|
103
|
+
"parameters": {"type": "object", "properties": {}},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "fahali_recent_alerts",
|
|
107
|
+
"description": "Latest engine detections (volume anomalies, dark-pool proxy, regime flips, whale flows...) across ~600 instruments.",
|
|
108
|
+
"parameters": {"type": "object", "properties": {}},
|
|
109
|
+
},
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def execute_tool(client: FahaliClient, name: str, args: Optional[dict[str, Any]] = None) -> Any:
|
|
114
|
+
"""Execute a TOOL_SPECS call by name."""
|
|
115
|
+
a = args or {}
|
|
116
|
+
if name == "fahali_verdict":
|
|
117
|
+
return client.verdict(list(a.get("symbols") or []))
|
|
118
|
+
if name == "fahali_forecast_72h":
|
|
119
|
+
return client.forecast_72h(str(a.get("symbol", "")))
|
|
120
|
+
if name == "fahali_tape":
|
|
121
|
+
return client.tape()
|
|
122
|
+
if name == "fahali_symbol_record":
|
|
123
|
+
return client.symbol_record(str(a.get("symbol", "")))
|
|
124
|
+
if name == "fahali_track_record":
|
|
125
|
+
return client.track_record()
|
|
126
|
+
if name == "fahali_recent_alerts":
|
|
127
|
+
return client.recent_alerts()
|
|
128
|
+
raise FahaliError(f"Unknown Fahali tool: {name}")
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""CrewAI adapter: `pip install fahali crewai-tools`."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from . import FahaliClient, execute_tool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_crewai_tools(client: FahaliClient) -> list:
|
|
7
|
+
"""BaseTool list for CrewAI agents."""
|
|
8
|
+
import json
|
|
9
|
+
from crewai.tools import tool # lazy
|
|
10
|
+
|
|
11
|
+
@tool("fahali_verdict")
|
|
12
|
+
def fahali_verdict(symbols: str) -> str:
|
|
13
|
+
"""Committee market verdict for comma-separated symbols (e.g. 'BTCUSDT,ETHUSDT'). 18 engines vote; includes agreement, dissent on the record, a signed receipt and a public replay URL. Observation, not advice."""
|
|
14
|
+
return json.dumps(execute_tool(client, "fahali_verdict", {"symbols": symbols.split(",")}))
|
|
15
|
+
|
|
16
|
+
@tool("fahali_forecast_72h")
|
|
17
|
+
def fahali_forecast_72h(symbol: str) -> str:
|
|
18
|
+
"""72-hour crash/neutral/pump probability forecast for one symbol, Brier-calibrated."""
|
|
19
|
+
return json.dumps(execute_tool(client, "fahali_forecast_72h", {"symbol": symbol}))
|
|
20
|
+
|
|
21
|
+
@tool("fahali_tape")
|
|
22
|
+
def fahali_tape() -> str:
|
|
23
|
+
"""The live tape: latest judged calls, hits AND misses, with replay URLs."""
|
|
24
|
+
return json.dumps(execute_tool(client, "fahali_tape"))
|
|
25
|
+
|
|
26
|
+
@tool("fahali_symbol_record")
|
|
27
|
+
def fahali_symbol_record(symbol: str) -> str:
|
|
28
|
+
"""Judged track record for one symbol - last 9 calls, misses included."""
|
|
29
|
+
return json.dumps(execute_tool(client, "fahali_symbol_record", {"symbol": symbol}))
|
|
30
|
+
|
|
31
|
+
@tool("fahali_track_record")
|
|
32
|
+
def fahali_track_record() -> str:
|
|
33
|
+
"""Aggregate scorecard with sample sizes and disclosed gaps - read lift vs base rate."""
|
|
34
|
+
return json.dumps(execute_tool(client, "fahali_track_record"))
|
|
35
|
+
|
|
36
|
+
return [fahali_verdict, fahali_forecast_72h, fahali_tape, fahali_symbol_record, fahali_track_record]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""LangChain adapter: `pip install fahali langchain-core`."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from typing import Any
|
|
4
|
+
from . import FahaliClient, TOOL_SPECS, execute_tool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_langchain_tools(client: FahaliClient) -> list:
|
|
8
|
+
"""StructuredTool list for LangChain / LangGraph agents."""
|
|
9
|
+
from langchain_core.tools import StructuredTool # lazy
|
|
10
|
+
|
|
11
|
+
tools = []
|
|
12
|
+
for spec in TOOL_SPECS:
|
|
13
|
+
def _make(name: str):
|
|
14
|
+
def _run(**kwargs: Any) -> str:
|
|
15
|
+
import json
|
|
16
|
+
return json.dumps(execute_tool(client, name, kwargs))
|
|
17
|
+
return _run
|
|
18
|
+
tools.append(StructuredTool.from_function(
|
|
19
|
+
func=_make(spec["name"]), name=spec["name"],
|
|
20
|
+
description=spec["description"], args_schema=None,
|
|
21
|
+
))
|
|
22
|
+
return tools
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""LlamaIndex adapter: `pip install fahali llama-index-core`."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from . import FahaliClient, TOOL_SPECS, execute_tool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_llamaindex_tools(client: FahaliClient) -> list:
|
|
7
|
+
"""FunctionTool list for LlamaIndex agents."""
|
|
8
|
+
import json
|
|
9
|
+
from llama_index.core.tools import FunctionTool # lazy
|
|
10
|
+
|
|
11
|
+
tools = []
|
|
12
|
+
for spec in TOOL_SPECS:
|
|
13
|
+
def _make(name: str):
|
|
14
|
+
def _run(**kwargs) -> str:
|
|
15
|
+
return json.dumps(execute_tool(client, name, kwargs))
|
|
16
|
+
_run.__name__ = name
|
|
17
|
+
return _run
|
|
18
|
+
tools.append(FunctionTool.from_defaults(fn=_make(spec["name"]), name=spec["name"], description=spec["description"]))
|
|
19
|
+
return tools
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fahali"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Market intelligence AI agents can verify - signed receipts, judged track record (misses included), Brier-calibrated forecasts. Adapters for LangChain, CrewAI, LlamaIndex, AutoGen, smolagents. MCP: mcp.fahaliai.com"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{ name = "Future Legends AI", email = "robert@futurelegendsai.com" }]
|
|
13
|
+
keywords = ["ai-agents", "mcp", "market-intelligence", "langchain", "crewai", "llamaindex", "function-calling", "crypto", "risk"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://fahaliai.com/developer"
|
|
23
|
+
Documentation = "https://fahaliai.com/developer"
|
|
24
|
+
Repository = "https://github.com/BobMain-2025/fahali-integrations"
|