google-adk-surface 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.
@@ -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.
@@ -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,31 @@
1
+ # google-adk-surface
2
+
3
+ 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).
4
+
5
+ ```python
6
+ from google.adk.agents import Agent
7
+ from google_adk_surface import surface_preflight
8
+
9
+ agent = Agent(name="web", model="gemini-2.0-flash", tools=[surface_preflight])
10
+ ```
11
+
12
+ ## Free to start
13
+
14
+ 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:
15
+
16
+ ```bash
17
+ curl -s -X POST https://nova-otter-delta-cloud.grok.me/v1/keys
18
+ export SURFACE_API_KEY=...
19
+ ```
20
+
21
+ After the free tier: $0.25 USD per 1,000 preflights.
22
+
23
+ ## Prefer MCP?
24
+
25
+ Point any MCP client at `https://nova-otter-delta-cloud.grok.me/mcp` (tool `preflight_url`).
26
+
27
+ - Website: https://otter-sand-wolf-spring.grok.me
28
+ - Docs: https://nova-otter-delta-cloud.grok.me/docs
29
+ - LLM reference: https://nova-otter-delta-cloud.grok.me/llms.txt
30
+
31
+ Made by Canada Site Ops. MIT licensed.
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "google-adk-surface"
7
+ version = "0.1.0"
8
+ description = "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."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [{name = "Canada Site Ops", email = "canada.site.ops@gmail.com"}]
13
+ maintainers = [{name = "Canada Site Ops", email = "canada.site.ops@gmail.com"}]
14
+ keywords = ["google-adk","adk","gemini","ai-agents","link-safety","url","preflight","mcp","surface","tools"]
15
+ dependencies = ["google-adk>=1.0"]
16
+ classifiers = ["Programming Language :: Python :: 3","License :: OSI Approved :: MIT License","Topic :: Internet :: WWW/HTTP"]
17
+
18
+ [project.urls]
19
+ Homepage = "https://otter-sand-wolf-spring.grok.me"
20
+ Documentation = "https://nova-otter-delta-cloud.grok.me/docs"
21
+ "API reference" = "https://nova-otter-delta-cloud.grok.me/llms.txt"
22
+ "MCP server" = "https://nova-otter-delta-cloud.grok.me/mcp"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["src/google_adk_surface"]
@@ -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)})