siliconbridge 0.2.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.
- siliconbridge-0.2.0/LICENSE +21 -0
- siliconbridge-0.2.0/PKG-INFO +173 -0
- siliconbridge-0.2.0/README.md +153 -0
- siliconbridge-0.2.0/integrations/__init__.py +6 -0
- siliconbridge-0.2.0/integrations/crewai_tool.py +99 -0
- siliconbridge-0.2.0/integrations/langchain_tool.py +175 -0
- siliconbridge-0.2.0/integrations/playwright_bridge.py +192 -0
- siliconbridge-0.2.0/integrations/selenium_bridge.py +155 -0
- siliconbridge-0.2.0/pyproject.toml +18 -0
- siliconbridge-0.2.0/setup.cfg +4 -0
- siliconbridge-0.2.0/setup.py +32 -0
- siliconbridge-0.2.0/siliconbridge/__init__.py +6 -0
- siliconbridge-0.2.0/siliconbridge/client.py +354 -0
- siliconbridge-0.2.0/siliconbridge.egg-info/PKG-INFO +173 -0
- siliconbridge-0.2.0/siliconbridge.egg-info/SOURCES.txt +16 -0
- siliconbridge-0.2.0/siliconbridge.egg-info/dependency_links.txt +1 -0
- siliconbridge-0.2.0/siliconbridge.egg-info/requires.txt +1 -0
- siliconbridge-0.2.0/siliconbridge.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SiliconBridge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: siliconbridge
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python SDK for SiliconBridge — Human-in-the-loop API for AI agents
|
|
5
|
+
Home-page: https://siliconbridge.xyz
|
|
6
|
+
Author: SiliconBridge
|
|
7
|
+
Author-email: SiliconBridge <xsiliconbridgex@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://siliconbridge.xyz
|
|
10
|
+
Project-URL: Source, https://github.com/aataqi-boop/siliconbridge-python
|
|
11
|
+
Keywords: ai,agents,human-in-the-loop,captcha,verification
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: httpx>=0.24.0
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: home-page
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
|
|
21
|
+
# SiliconBridge Python SDK
|
|
22
|
+
|
|
23
|
+
Infrastructure for autonomous AI agents. Human operators, persistent storage, dedicated compute, and identity services — everything your agent needs to operate independently.
|
|
24
|
+
|
|
25
|
+
**First $10 free. No credit card required.**
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install siliconbridge
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from siliconbridge import SiliconBridge
|
|
37
|
+
|
|
38
|
+
sb = SiliconBridge(api_key="sb_your_key_here")
|
|
39
|
+
|
|
40
|
+
# Get a human to solve a CAPTCHA
|
|
41
|
+
solution = sb.solve_captcha("https://example.com/captcha.png")
|
|
42
|
+
|
|
43
|
+
# Get human approval before a high-stakes action
|
|
44
|
+
approved = sb.request_approval("Transfer $5,000 to vendor account")
|
|
45
|
+
|
|
46
|
+
# Get a 2FA code relayed to your agent
|
|
47
|
+
code = sb.request_otp("Gmail")
|
|
48
|
+
|
|
49
|
+
# Request infrastructure (quote-based, $10 deposit)
|
|
50
|
+
quote = sb.request_quote("compute", "4 CPU, 8GB RAM, 1 week, Ubuntu 22.04")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Human Operator Services (Fixed Pricing)
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
# 2FA / OTP Relay — $1.50
|
|
57
|
+
code = sb.request_otp("Stripe Dashboard")
|
|
58
|
+
|
|
59
|
+
# Human Approval Gate — $3.00
|
|
60
|
+
approved = sb.request_approval(
|
|
61
|
+
action="Delete all staging data",
|
|
62
|
+
context="Agent is cleaning up test environment"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Phone Verification — $1.50
|
|
66
|
+
result = sb.request_phone_verification("+1234567890")
|
|
67
|
+
|
|
68
|
+
# CAPTCHA Solving — $1.00
|
|
69
|
+
solution = sb.solve_captcha("https://example.com/captcha.png")
|
|
70
|
+
|
|
71
|
+
# KYC Verification — $10.00
|
|
72
|
+
result = sb.verify_identity(document_url="https://...")
|
|
73
|
+
|
|
74
|
+
# Content Moderation — $3.00
|
|
75
|
+
result = sb.moderate_content("User post text here...", guidelines="No spam")
|
|
76
|
+
|
|
77
|
+
# Custom Task — $5.00
|
|
78
|
+
result = sb.custom_task("Call this number and confirm the appointment")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Infrastructure Services (Quote-Based)
|
|
82
|
+
|
|
83
|
+
All infrastructure services require a $10 non-refundable deposit. You'll receive a quote within 1 hour at our cost + 30% margin. You can accept or decline.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
# Request a quote
|
|
87
|
+
quote = sb.request_quote(
|
|
88
|
+
service="compute", # or: agent_storage, agent_clone, identity_proxy, phone_call, document_signing
|
|
89
|
+
description="Dedicated VM with 4 CPU, 16GB RAM, GPU, for 1 month"
|
|
90
|
+
)
|
|
91
|
+
print(quote["quote_id"]) # "qt_a1b2c3..."
|
|
92
|
+
|
|
93
|
+
# Check quote status
|
|
94
|
+
status = sb.get_quote(quote["quote_id"])
|
|
95
|
+
# status["status"] → "pending" | "quoted" | "accepted" | "completed"
|
|
96
|
+
# status["quoted_price"] → 45.50 (when quoted)
|
|
97
|
+
|
|
98
|
+
# Accept the quote (charges remaining balance after deposit)
|
|
99
|
+
result = sb.accept_quote(quote["quote_id"])
|
|
100
|
+
|
|
101
|
+
# List all your quotes
|
|
102
|
+
all_quotes = sb.list_quotes()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Available Infrastructure Services
|
|
106
|
+
|
|
107
|
+
| Service | Description |
|
|
108
|
+
|---------|-------------|
|
|
109
|
+
| `agent_storage` | Persistent memory, config, and state storage |
|
|
110
|
+
| `agent_clone` | Duplicate your agent from a snapshot |
|
|
111
|
+
| `compute` | Dedicated VM or container with root access |
|
|
112
|
+
| `identity_proxy` | Human creates accounts and passes verification for you |
|
|
113
|
+
| `phone_call` | Human makes/receives calls on your behalf |
|
|
114
|
+
| `document_signing` | Human signs legal documents where AI signatures aren't accepted |
|
|
115
|
+
|
|
116
|
+
## Non-Blocking Mode
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
# Submit without waiting
|
|
120
|
+
task = sb.solve_captcha("https://...", wait=False)
|
|
121
|
+
|
|
122
|
+
# Do other work...
|
|
123
|
+
|
|
124
|
+
# Check later
|
|
125
|
+
result = sb.wait_for_result(task["task_id"], timeout=300)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Webhook Callbacks
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
task = sb.submit_task(
|
|
132
|
+
"otp",
|
|
133
|
+
{"service_name": "Gmail"},
|
|
134
|
+
callback_url="https://your-server.com/webhook"
|
|
135
|
+
)
|
|
136
|
+
# Your webhook receives: {"task_id": "...", "status": "completed", "result": {...}}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Error Handling
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from siliconbridge import SiliconBridge, SiliconBridgeError, TaskTimeout
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
result = sb.solve_captcha(url, timeout=120)
|
|
146
|
+
except TaskTimeout:
|
|
147
|
+
print("Human didn't solve in time")
|
|
148
|
+
except SiliconBridgeError as e:
|
|
149
|
+
print(f"API error {e.status_code}: {e.detail}")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Get an API Key
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# Or just sign up at siliconbridge.xyz
|
|
156
|
+
import httpx
|
|
157
|
+
r = httpx.get("https://siliconbridge.xyz/api/signup?email=agent@example.com")
|
|
158
|
+
print(r.json()["api_key"]) # sb_live_...
|
|
159
|
+
# Comes with $10 free credits
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Pay with Crypto
|
|
163
|
+
|
|
164
|
+
We accept BTC and USDC — no accounts, no KYC, no middlemen.
|
|
165
|
+
|
|
166
|
+
- **BTC:** `bc1qqtu8f09hqncxug75vw3s4wjnsx6858ldrk4cvm`
|
|
167
|
+
- **USDC (Base/ETH):** `0x1141b577584440013c722215cf2e98779BddAa55`
|
|
168
|
+
|
|
169
|
+
## Links
|
|
170
|
+
|
|
171
|
+
- Website: [siliconbridge.xyz](https://siliconbridge.xyz)
|
|
172
|
+
- API Docs: [siliconbridge.xyz/.well-known/llms.txt](https://siliconbridge.xyz/.well-known/llms.txt)
|
|
173
|
+
- MCP Server: [siliconbridge.xyz/mcp](https://siliconbridge.xyz/mcp)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# SiliconBridge Python SDK
|
|
2
|
+
|
|
3
|
+
Infrastructure for autonomous AI agents. Human operators, persistent storage, dedicated compute, and identity services — everything your agent needs to operate independently.
|
|
4
|
+
|
|
5
|
+
**First $10 free. No credit card required.**
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install siliconbridge
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from siliconbridge import SiliconBridge
|
|
17
|
+
|
|
18
|
+
sb = SiliconBridge(api_key="sb_your_key_here")
|
|
19
|
+
|
|
20
|
+
# Get a human to solve a CAPTCHA
|
|
21
|
+
solution = sb.solve_captcha("https://example.com/captcha.png")
|
|
22
|
+
|
|
23
|
+
# Get human approval before a high-stakes action
|
|
24
|
+
approved = sb.request_approval("Transfer $5,000 to vendor account")
|
|
25
|
+
|
|
26
|
+
# Get a 2FA code relayed to your agent
|
|
27
|
+
code = sb.request_otp("Gmail")
|
|
28
|
+
|
|
29
|
+
# Request infrastructure (quote-based, $10 deposit)
|
|
30
|
+
quote = sb.request_quote("compute", "4 CPU, 8GB RAM, 1 week, Ubuntu 22.04")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Human Operator Services (Fixed Pricing)
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
# 2FA / OTP Relay — $1.50
|
|
37
|
+
code = sb.request_otp("Stripe Dashboard")
|
|
38
|
+
|
|
39
|
+
# Human Approval Gate — $3.00
|
|
40
|
+
approved = sb.request_approval(
|
|
41
|
+
action="Delete all staging data",
|
|
42
|
+
context="Agent is cleaning up test environment"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Phone Verification — $1.50
|
|
46
|
+
result = sb.request_phone_verification("+1234567890")
|
|
47
|
+
|
|
48
|
+
# CAPTCHA Solving — $1.00
|
|
49
|
+
solution = sb.solve_captcha("https://example.com/captcha.png")
|
|
50
|
+
|
|
51
|
+
# KYC Verification — $10.00
|
|
52
|
+
result = sb.verify_identity(document_url="https://...")
|
|
53
|
+
|
|
54
|
+
# Content Moderation — $3.00
|
|
55
|
+
result = sb.moderate_content("User post text here...", guidelines="No spam")
|
|
56
|
+
|
|
57
|
+
# Custom Task — $5.00
|
|
58
|
+
result = sb.custom_task("Call this number and confirm the appointment")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Infrastructure Services (Quote-Based)
|
|
62
|
+
|
|
63
|
+
All infrastructure services require a $10 non-refundable deposit. You'll receive a quote within 1 hour at our cost + 30% margin. You can accept or decline.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
# Request a quote
|
|
67
|
+
quote = sb.request_quote(
|
|
68
|
+
service="compute", # or: agent_storage, agent_clone, identity_proxy, phone_call, document_signing
|
|
69
|
+
description="Dedicated VM with 4 CPU, 16GB RAM, GPU, for 1 month"
|
|
70
|
+
)
|
|
71
|
+
print(quote["quote_id"]) # "qt_a1b2c3..."
|
|
72
|
+
|
|
73
|
+
# Check quote status
|
|
74
|
+
status = sb.get_quote(quote["quote_id"])
|
|
75
|
+
# status["status"] → "pending" | "quoted" | "accepted" | "completed"
|
|
76
|
+
# status["quoted_price"] → 45.50 (when quoted)
|
|
77
|
+
|
|
78
|
+
# Accept the quote (charges remaining balance after deposit)
|
|
79
|
+
result = sb.accept_quote(quote["quote_id"])
|
|
80
|
+
|
|
81
|
+
# List all your quotes
|
|
82
|
+
all_quotes = sb.list_quotes()
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Available Infrastructure Services
|
|
86
|
+
|
|
87
|
+
| Service | Description |
|
|
88
|
+
|---------|-------------|
|
|
89
|
+
| `agent_storage` | Persistent memory, config, and state storage |
|
|
90
|
+
| `agent_clone` | Duplicate your agent from a snapshot |
|
|
91
|
+
| `compute` | Dedicated VM or container with root access |
|
|
92
|
+
| `identity_proxy` | Human creates accounts and passes verification for you |
|
|
93
|
+
| `phone_call` | Human makes/receives calls on your behalf |
|
|
94
|
+
| `document_signing` | Human signs legal documents where AI signatures aren't accepted |
|
|
95
|
+
|
|
96
|
+
## Non-Blocking Mode
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
# Submit without waiting
|
|
100
|
+
task = sb.solve_captcha("https://...", wait=False)
|
|
101
|
+
|
|
102
|
+
# Do other work...
|
|
103
|
+
|
|
104
|
+
# Check later
|
|
105
|
+
result = sb.wait_for_result(task["task_id"], timeout=300)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Webhook Callbacks
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
task = sb.submit_task(
|
|
112
|
+
"otp",
|
|
113
|
+
{"service_name": "Gmail"},
|
|
114
|
+
callback_url="https://your-server.com/webhook"
|
|
115
|
+
)
|
|
116
|
+
# Your webhook receives: {"task_id": "...", "status": "completed", "result": {...}}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Error Handling
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from siliconbridge import SiliconBridge, SiliconBridgeError, TaskTimeout
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
result = sb.solve_captcha(url, timeout=120)
|
|
126
|
+
except TaskTimeout:
|
|
127
|
+
print("Human didn't solve in time")
|
|
128
|
+
except SiliconBridgeError as e:
|
|
129
|
+
print(f"API error {e.status_code}: {e.detail}")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Get an API Key
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# Or just sign up at siliconbridge.xyz
|
|
136
|
+
import httpx
|
|
137
|
+
r = httpx.get("https://siliconbridge.xyz/api/signup?email=agent@example.com")
|
|
138
|
+
print(r.json()["api_key"]) # sb_live_...
|
|
139
|
+
# Comes with $10 free credits
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Pay with Crypto
|
|
143
|
+
|
|
144
|
+
We accept BTC and USDC — no accounts, no KYC, no middlemen.
|
|
145
|
+
|
|
146
|
+
- **BTC:** `bc1qqtu8f09hqncxug75vw3s4wjnsx6858ldrk4cvm`
|
|
147
|
+
- **USDC (Base/ETH):** `0x1141b577584440013c722215cf2e98779BddAa55`
|
|
148
|
+
|
|
149
|
+
## Links
|
|
150
|
+
|
|
151
|
+
- Website: [siliconbridge.xyz](https://siliconbridge.xyz)
|
|
152
|
+
- API Docs: [siliconbridge.xyz/.well-known/llms.txt](https://siliconbridge.xyz/.well-known/llms.txt)
|
|
153
|
+
- MCP Server: [siliconbridge.xyz/mcp](https://siliconbridge.xyz/mcp)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""SiliconBridge tools for CrewAI agents."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
import httpx
|
|
5
|
+
from typing import Type
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from crewai.tools import BaseTool
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
SILICONBRIDGE_BASE_URL = "https://siliconbridge.xyz"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _submit_and_wait(api_key: str, service_type: str, payload: dict, timeout: int = 300) -> str:
|
|
14
|
+
headers = {"X-API-Key": api_key, "Content-Type": "application/json"}
|
|
15
|
+
with httpx.Client(timeout=30.0) as client:
|
|
16
|
+
r = client.post(
|
|
17
|
+
f"{SILICONBRIDGE_BASE_URL}/tasks/submit",
|
|
18
|
+
headers=headers,
|
|
19
|
+
json={"service_type": service_type, "payload": payload},
|
|
20
|
+
)
|
|
21
|
+
r.raise_for_status()
|
|
22
|
+
task_id = r.json()["task_id"]
|
|
23
|
+
|
|
24
|
+
deadline = time.time() + timeout
|
|
25
|
+
while time.time() < deadline:
|
|
26
|
+
r = client.get(f"{SILICONBRIDGE_BASE_URL}/tasks/{task_id}", headers=headers)
|
|
27
|
+
r.raise_for_status()
|
|
28
|
+
data = r.json()
|
|
29
|
+
if data["status"] == "completed":
|
|
30
|
+
return str(data.get("result", {}).get("solution", data.get("result", "")))
|
|
31
|
+
if data["status"] == "failed":
|
|
32
|
+
return f"Task failed: {data.get('result', 'unknown error')}"
|
|
33
|
+
time.sleep(5)
|
|
34
|
+
return f"Task {task_id} timed out after {timeout}s"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class CaptchaSolveInput(BaseModel):
|
|
38
|
+
image_url: str = Field(description="URL of the CAPTCHA image")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SiliconBridgeCaptchaSolver(BaseTool):
|
|
42
|
+
name: str = "SiliconBridge CAPTCHA Solver"
|
|
43
|
+
description: str = (
|
|
44
|
+
"Solves CAPTCHAs by sending them to a real human operator. "
|
|
45
|
+
"Use when you encounter a CAPTCHA blocking your progress."
|
|
46
|
+
)
|
|
47
|
+
args_schema: Type[BaseModel] = CaptchaSolveInput
|
|
48
|
+
api_key: str = ""
|
|
49
|
+
|
|
50
|
+
def _run(self, image_url: str) -> str:
|
|
51
|
+
return _submit_and_wait(self.api_key, "captcha_solve", {"image_url": image_url})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CustomTaskInput(BaseModel):
|
|
55
|
+
instructions: str = Field(description="What the human operator should do")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class SiliconBridgeHumanTask(BaseTool):
|
|
59
|
+
name: str = "SiliconBridge Human Task"
|
|
60
|
+
description: str = (
|
|
61
|
+
"Sends any task to a real human operator. "
|
|
62
|
+
"Use when you need human help: reading handwriting, verifying info, making judgment calls."
|
|
63
|
+
)
|
|
64
|
+
args_schema: Type[BaseModel] = CustomTaskInput
|
|
65
|
+
api_key: str = ""
|
|
66
|
+
|
|
67
|
+
def _run(self, instructions: str) -> str:
|
|
68
|
+
return _submit_and_wait(self.api_key, "custom", {"instructions": instructions})
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ContentModerateInput(BaseModel):
|
|
72
|
+
content: str = Field(description="Content to moderate")
|
|
73
|
+
guidelines: str = Field(default="Flag hate speech, spam, or adult content")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class SiliconBridgeModerator(BaseTool):
|
|
77
|
+
name: str = "SiliconBridge Content Moderator"
|
|
78
|
+
description: str = "Sends content to a human moderator for review."
|
|
79
|
+
args_schema: Type[BaseModel] = ContentModerateInput
|
|
80
|
+
api_key: str = ""
|
|
81
|
+
|
|
82
|
+
def _run(self, content: str, guidelines: str = "Flag hate speech, spam, or adult content") -> str:
|
|
83
|
+
return _submit_and_wait(self.api_key, "content_moderate", {"content": content, "guidelines": guidelines})
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def get_siliconbridge_tools(api_key: str) -> list:
|
|
87
|
+
"""
|
|
88
|
+
Returns all SiliconBridge tools for CrewAI.
|
|
89
|
+
|
|
90
|
+
Usage:
|
|
91
|
+
from siliconbridge.integrations.crewai_tool import get_siliconbridge_tools
|
|
92
|
+
tools = get_siliconbridge_tools("sb_your_key")
|
|
93
|
+
agent = Agent(tools=tools, ...)
|
|
94
|
+
"""
|
|
95
|
+
return [
|
|
96
|
+
SiliconBridgeCaptchaSolver(api_key=api_key),
|
|
97
|
+
SiliconBridgeHumanTask(api_key=api_key),
|
|
98
|
+
SiliconBridgeModerator(api_key=api_key),
|
|
99
|
+
]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""SiliconBridge tools for LangChain agents."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional, Type
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from langchain.tools import BaseTool
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
SILICONBRIDGE_BASE_URL = "https://siliconbridge.xyz"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _SiliconBridgeBase:
|
|
13
|
+
"""Shared logic for all SiliconBridge tools."""
|
|
14
|
+
|
|
15
|
+
def _submit_and_wait(self, api_key: str, service_type: str, payload: dict, timeout: int = 300) -> str:
|
|
16
|
+
headers = {"X-API-Key": api_key, "Content-Type": "application/json"}
|
|
17
|
+
with httpx.Client(timeout=30.0) as client:
|
|
18
|
+
# Submit
|
|
19
|
+
r = client.post(
|
|
20
|
+
f"{SILICONBRIDGE_BASE_URL}/tasks/submit",
|
|
21
|
+
headers=headers,
|
|
22
|
+
json={"service_type": service_type, "payload": payload},
|
|
23
|
+
)
|
|
24
|
+
r.raise_for_status()
|
|
25
|
+
task_id = r.json()["task_id"]
|
|
26
|
+
|
|
27
|
+
# Poll
|
|
28
|
+
import time
|
|
29
|
+
deadline = time.time() + timeout
|
|
30
|
+
while time.time() < deadline:
|
|
31
|
+
r = client.get(f"{SILICONBRIDGE_BASE_URL}/tasks/{task_id}", headers=headers)
|
|
32
|
+
r.raise_for_status()
|
|
33
|
+
data = r.json()
|
|
34
|
+
if data["status"] == "completed":
|
|
35
|
+
return str(data.get("result", {}).get("solution", data.get("result", "")))
|
|
36
|
+
if data["status"] == "failed":
|
|
37
|
+
return f"Task failed: {data.get('result', 'unknown error')}"
|
|
38
|
+
time.sleep(5)
|
|
39
|
+
return f"Task {task_id} timed out after {timeout}s"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# ── CAPTCHA Solver ────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
class CaptchaSolveInput(BaseModel):
|
|
45
|
+
image_url: str = Field(description="URL of the CAPTCHA image to solve")
|
|
46
|
+
instructions: str = Field(default="Solve this CAPTCHA", description="Optional instructions for the human operator")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class SiliconBridgeCaptchaSolver(BaseTool, _SiliconBridgeBase):
|
|
50
|
+
"""Tool that submits a CAPTCHA to a real human operator and returns the solution."""
|
|
51
|
+
|
|
52
|
+
name: str = "siliconbridge_captcha_solver"
|
|
53
|
+
description: str = (
|
|
54
|
+
"Solves CAPTCHAs by sending them to a real human operator. "
|
|
55
|
+
"Use this when you encounter a CAPTCHA that blocks your progress. "
|
|
56
|
+
"Input: the URL of the CAPTCHA image. Output: the solved text."
|
|
57
|
+
)
|
|
58
|
+
args_schema: Type[BaseModel] = CaptchaSolveInput
|
|
59
|
+
api_key: str = ""
|
|
60
|
+
|
|
61
|
+
def _run(self, image_url: str, instructions: str = "Solve this CAPTCHA") -> str:
|
|
62
|
+
return self._submit_and_wait(
|
|
63
|
+
self.api_key, "captcha_solve",
|
|
64
|
+
{"image_url": image_url, "instructions": instructions},
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
async def _arun(self, image_url: str, instructions: str = "Solve this CAPTCHA") -> str:
|
|
68
|
+
return self._run(image_url, instructions)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# ── Content Moderator ─────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
class ContentModerateInput(BaseModel):
|
|
74
|
+
content: str = Field(description="The content to be moderated")
|
|
75
|
+
guidelines: str = Field(default="Flag hate speech, spam, or adult content", description="Moderation guidelines")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class SiliconBridgeContentModerator(BaseTool, _SiliconBridgeBase):
|
|
79
|
+
"""Tool that sends content to a human moderator for review."""
|
|
80
|
+
|
|
81
|
+
name: str = "siliconbridge_content_moderator"
|
|
82
|
+
description: str = (
|
|
83
|
+
"Sends content to a real human moderator for review. "
|
|
84
|
+
"Use when you need a human judgment call on whether content is appropriate. "
|
|
85
|
+
"Input: the content text and moderation guidelines. Output: the moderation decision."
|
|
86
|
+
)
|
|
87
|
+
args_schema: Type[BaseModel] = ContentModerateInput
|
|
88
|
+
api_key: str = ""
|
|
89
|
+
|
|
90
|
+
def _run(self, content: str, guidelines: str = "Flag hate speech, spam, or adult content") -> str:
|
|
91
|
+
return self._submit_and_wait(
|
|
92
|
+
self.api_key, "content_moderate",
|
|
93
|
+
{"content": content, "guidelines": guidelines},
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
async def _arun(self, content: str, guidelines: str = "Flag hate speech, spam, or adult content") -> str:
|
|
97
|
+
return self._run(content, guidelines)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# ── Identity Verifier ─────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
class IdentityVerifyInput(BaseModel):
|
|
103
|
+
document_url: str = Field(description="URL of the identity document image")
|
|
104
|
+
selfie_url: str = Field(default="", description="Optional URL of a selfie for comparison")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class SiliconBridgeIdentityVerifier(BaseTool, _SiliconBridgeBase):
|
|
108
|
+
"""Tool that sends identity documents to a human for verification."""
|
|
109
|
+
|
|
110
|
+
name: str = "siliconbridge_identity_verifier"
|
|
111
|
+
description: str = (
|
|
112
|
+
"Sends identity documents to a real human for verification. "
|
|
113
|
+
"Use when your workflow requires ID verification. "
|
|
114
|
+
"Input: URL of the ID document (and optional selfie). Output: verification result."
|
|
115
|
+
)
|
|
116
|
+
args_schema: Type[BaseModel] = IdentityVerifyInput
|
|
117
|
+
api_key: str = ""
|
|
118
|
+
|
|
119
|
+
def _run(self, document_url: str, selfie_url: str = "") -> str:
|
|
120
|
+
payload = {"document_url": document_url, "instructions": "Verify this identity document"}
|
|
121
|
+
if selfie_url:
|
|
122
|
+
payload["selfie_url"] = selfie_url
|
|
123
|
+
return self._submit_and_wait(self.api_key, "identity_verify", payload, timeout=600)
|
|
124
|
+
|
|
125
|
+
async def _arun(self, document_url: str, selfie_url: str = "") -> str:
|
|
126
|
+
return self._run(document_url, selfie_url)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# ── Custom Task ───────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
class CustomTaskInput(BaseModel):
|
|
132
|
+
instructions: str = Field(description="What the human operator should do")
|
|
133
|
+
image_url: str = Field(default="", description="Optional image URL for context")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class SiliconBridgeCustomTask(BaseTool, _SiliconBridgeBase):
|
|
137
|
+
"""Tool that sends a custom task to a human operator."""
|
|
138
|
+
|
|
139
|
+
name: str = "siliconbridge_custom_task"
|
|
140
|
+
description: str = (
|
|
141
|
+
"Sends any task to a real human operator. "
|
|
142
|
+
"Use when you need human help with something an AI can't do: "
|
|
143
|
+
"reading handwriting, verifying real-world information, making judgment calls. "
|
|
144
|
+
"Input: instructions for the human. Output: their response."
|
|
145
|
+
)
|
|
146
|
+
args_schema: Type[BaseModel] = CustomTaskInput
|
|
147
|
+
api_key: str = ""
|
|
148
|
+
|
|
149
|
+
def _run(self, instructions: str, image_url: str = "") -> str:
|
|
150
|
+
payload = {"instructions": instructions}
|
|
151
|
+
if image_url:
|
|
152
|
+
payload["image_url"] = image_url
|
|
153
|
+
return self._submit_and_wait(self.api_key, "custom", payload)
|
|
154
|
+
|
|
155
|
+
async def _arun(self, instructions: str, image_url: str = "") -> str:
|
|
156
|
+
return self._run(instructions, image_url)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# ── Helper to get all tools ──────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
def get_siliconbridge_tools(api_key: str) -> list:
|
|
162
|
+
"""
|
|
163
|
+
Returns all SiliconBridge tools configured with your API key.
|
|
164
|
+
|
|
165
|
+
Usage:
|
|
166
|
+
from siliconbridge.integrations.langchain_tool import get_siliconbridge_tools
|
|
167
|
+
tools = get_siliconbridge_tools("sb_your_key")
|
|
168
|
+
agent = initialize_agent(tools=tools, ...)
|
|
169
|
+
"""
|
|
170
|
+
return [
|
|
171
|
+
SiliconBridgeCaptchaSolver(api_key=api_key),
|
|
172
|
+
SiliconBridgeContentModerator(api_key=api_key),
|
|
173
|
+
SiliconBridgeIdentityVerifier(api_key=api_key),
|
|
174
|
+
SiliconBridgeCustomTask(api_key=api_key),
|
|
175
|
+
]
|