google-adk-surface 0.1.0__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.
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Surface for Google ADK: the link-safety layer between an AI agent and the open web."""
|
|
2
|
+
from google.adk.tools import FunctionTool
|
|
3
|
+
from ._core import preflight, preflight_text, TOOL_DESCRIPTION
|
|
4
|
+
|
|
5
|
+
def surface_preflight(url: str) -> str:
|
|
6
|
+
"""Check a link before you open it. Unwraps short links, follows redirects, and answers fetch or skip plus where the link really goes.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
url: The link to check.
|
|
10
|
+
"""
|
|
11
|
+
return preflight_text(url, ua="google-adk-surface/0.1.0")
|
|
12
|
+
|
|
13
|
+
surface_preflight_tool = FunctionTool(surface_preflight)
|
|
14
|
+
|
|
15
|
+
__all__ = ["surface_preflight", "surface_preflight_tool", "preflight", "preflight_text", "TOOL_DESCRIPTION"]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Surface Preflight client: the link-safety layer between an AI agent and the open web."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import json, os, urllib.parse, urllib.request
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
DEFAULT_BASE_URL = "https://nova-otter-delta-cloud.grok.me"
|
|
7
|
+
TOOL_NAME = "surface_preflight"
|
|
8
|
+
TOOL_DESCRIPTION = (
|
|
9
|
+
"Check a link before you open it. Surface unwraps short links (t.co, bit.ly, "
|
|
10
|
+
"lnkd.in, youtu.be), follows redirects, and tells you whether the destination "
|
|
11
|
+
"is worth fetching ('fetch') or should be skipped ('skip'), plus where the "
|
|
12
|
+
"link really goes. It never returns the page itself."
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
def preflight(url: str, api_key: Optional[str] = None, base_url: Optional[str] = None,
|
|
16
|
+
timeout: float = 15.0, headers: Optional[Dict[str, str]] = None, ua: str = "surface-python/0.1.0") -> Dict[str, Any]:
|
|
17
|
+
"""Call Surface Preflight and return a compact verdict dict."""
|
|
18
|
+
base = (base_url or os.environ.get("SURFACE_BASE_URL") or DEFAULT_BASE_URL).rstrip("/")
|
|
19
|
+
key = api_key or os.environ.get("SURFACE_API_KEY")
|
|
20
|
+
h = {"Content-Type": "application/json", "Accept": "application/json",
|
|
21
|
+
"User-Agent": ua}
|
|
22
|
+
if key:
|
|
23
|
+
h["Authorization"] = "Bearer " + key
|
|
24
|
+
if headers:
|
|
25
|
+
h.update(headers)
|
|
26
|
+
req = urllib.request.Request(base + "/v1/preflight", data=json.dumps({"url": url}).encode(),
|
|
27
|
+
headers=h, method="POST")
|
|
28
|
+
with urllib.request.urlopen(req, timeout=timeout) as r:
|
|
29
|
+
data = json.loads(r.read().decode())
|
|
30
|
+
nxt = data.get("next") or data.get("verdict")
|
|
31
|
+
return {
|
|
32
|
+
"next": nxt,
|
|
33
|
+
"fetch": nxt == "fetch",
|
|
34
|
+
"url": data.get("url", url),
|
|
35
|
+
"final_url": data.get("final_url"),
|
|
36
|
+
"final_host": data.get("final_host"),
|
|
37
|
+
"status": data.get("status"),
|
|
38
|
+
"redirects": data.get("redirects"),
|
|
39
|
+
"shortener": data.get("shortener"),
|
|
40
|
+
"reason": data.get("reason"),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
def preflight_text(url: str, **kw: Any) -> str:
|
|
44
|
+
"""Same as preflight() but returns a JSON string, handy for LLM tool output."""
|
|
45
|
+
try:
|
|
46
|
+
return json.dumps(preflight(url, **kw))
|
|
47
|
+
except Exception as e: # tool output should never crash the agent loop
|
|
48
|
+
return json.dumps({"next": "skip", "fetch": False, "url": url, "error": str(e)})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: google-adk-surface
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Surface for Google ADK: the link-safety layer between an AI agent and the open web. One tool, surface_preflight, that tells your agent whether a link is worth fetching.
|
|
5
|
+
Project-URL: Homepage, https://otter-sand-wolf-spring.grok.me
|
|
6
|
+
Project-URL: Documentation, https://nova-otter-delta-cloud.grok.me/docs
|
|
7
|
+
Project-URL: API reference, https://nova-otter-delta-cloud.grok.me/llms.txt
|
|
8
|
+
Project-URL: MCP server, https://nova-otter-delta-cloud.grok.me/mcp
|
|
9
|
+
Author-email: Canada Site Ops <canada.site.ops@gmail.com>
|
|
10
|
+
Maintainer-email: Canada Site Ops <canada.site.ops@gmail.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: adk,ai-agents,gemini,google-adk,link-safety,mcp,preflight,surface,tools,url
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: google-adk>=1.0
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# google-adk-surface
|
|
22
|
+
|
|
23
|
+
Surface is the link-safety layer between an AI agent and the open web. One tool, `surface_preflight`: give it a URL, get `fetch` or `skip` plus where the link really goes (unwraps t.co, bit.ly, redirects).
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from google.adk.agents import Agent
|
|
27
|
+
from google_adk_surface import surface_preflight
|
|
28
|
+
|
|
29
|
+
agent = Agent(name="web", model="gemini-2.0-flash", tools=[surface_preflight])
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Free to start
|
|
33
|
+
|
|
34
|
+
The first 1M requests a month are free. It works with no key at all (shared demo limit), or grab your own free key in one call, with no email and no card:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
curl -s -X POST https://nova-otter-delta-cloud.grok.me/v1/keys
|
|
38
|
+
export SURFACE_API_KEY=...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
After the free tier: $0.25 USD per 1,000 preflights.
|
|
42
|
+
|
|
43
|
+
## Prefer MCP?
|
|
44
|
+
|
|
45
|
+
Point any MCP client at `https://nova-otter-delta-cloud.grok.me/mcp` (tool `preflight_url`).
|
|
46
|
+
|
|
47
|
+
- Website: https://otter-sand-wolf-spring.grok.me
|
|
48
|
+
- Docs: https://nova-otter-delta-cloud.grok.me/docs
|
|
49
|
+
- LLM reference: https://nova-otter-delta-cloud.grok.me/llms.txt
|
|
50
|
+
|
|
51
|
+
Made by Canada Site Ops. MIT licensed.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
google_adk_surface/__init__.py,sha256=Nwq3EiTq65oQc4YgOuB0oX7nS-YhtgwD00GYsuuN4Fc,656
|
|
2
|
+
google_adk_surface/_core.py,sha256=qatbSQobIepBZit1YIbTIgb01gXRe-STlwVWohtjJ3Q,2300
|
|
3
|
+
google_adk_surface-0.1.0.dist-info/METADATA,sha256=85JL7-5Db7QQYHzOsDnn_GHLJoEMuQItzT3P9zedTiw,2053
|
|
4
|
+
google_adk_surface-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
5
|
+
google_adk_surface-0.1.0.dist-info/licenses/LICENSE,sha256=fNLwqKpxzMvMZQTP1NQeJcBxAGsliU7T10uGRDcQeNo,675
|
|
6
|
+
google_adk_surface-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Canada Site Ops
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|