ai2web 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/lib/ai2web/export.rb +74 -0
- data/lib/ai2web/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1fe0e944f49b6072c4ae055b3d2db69492580564a0b2ea05f0f3ecf76bc98474
|
|
4
|
+
data.tar.gz: 62c79d2ecfc8f24a9351ba4cb6d82868f7c1877f2e1c16dd060dc1c2b3997384
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 809c65cb23a78846e260ff419aecabcc99eb22ab03802349bf22c51a90b9d513abbe5f5336d6792e727aa11c1dc1f604bc4508281a6a0253490c6cd3363a94af
|
|
7
|
+
data.tar.gz: 732da62ffbf60019317538d5fbcc56c74bcc73291c9e6d65afd09b073aced6d35bdd392d19198a94289dbebd1c34796b32ae17bfa5293e2e3109c5d2b7f31bea
|
data/lib/ai2web/export.rb
CHANGED
|
@@ -87,10 +87,84 @@ module Ai2Web
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
end
|
|
90
|
+
|
|
91
|
+
# OAuth 2.0 Protected Resource metadata (RFC 9728), for
|
|
92
|
+
# /.well-known/oauth-protected-resource. MCP clients read this to discover which
|
|
93
|
+
# authorization server guards the resource before starting a flow.
|
|
94
|
+
#
|
|
95
|
+
# Returns nil when the site does not advertise oauth2, so an auth surface the site cannot
|
|
96
|
+
# honour is never published.
|
|
97
|
+
def to_oauth_protected_resource(manifest)
|
|
98
|
+
m = Util.deep_stringify(manifest)
|
|
99
|
+
auth = m["auth"].is_a?(Hash) ? m["auth"] : {}
|
|
100
|
+
return nil unless Array(auth["methods"]).include?("oauth2")
|
|
101
|
+
|
|
102
|
+
site = m["site"].is_a?(Hash) ? m["site"] : {}
|
|
103
|
+
base = Util.trim_url(site["url"].to_s)
|
|
104
|
+
oauth2 = auth["oauth2"].is_a?(Hash) ? auth["oauth2"] : {}
|
|
105
|
+
issuer = base
|
|
106
|
+
authz = oauth2["authorization_url"].to_s
|
|
107
|
+
unless authz.empty?
|
|
108
|
+
begin
|
|
109
|
+
u = URI.parse(authz)
|
|
110
|
+
issuer = "#{u.scheme}://#{u.host}#{u.port && ![80, 443].include?(u.port) ? ":#{u.port}" : ""}" if u.scheme && u.host
|
|
111
|
+
rescue URI::InvalidURIError
|
|
112
|
+
# keep the site base as issuer
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
doc = {
|
|
116
|
+
"resource" => "#{base}/ai2w",
|
|
117
|
+
"authorization_servers" => [issuer],
|
|
118
|
+
"bearer_methods_supported" => ["header"]
|
|
119
|
+
}
|
|
120
|
+
scopes = oauth2["scopes"]
|
|
121
|
+
doc["scopes_supported"] = Array(scopes) if scopes && !Array(scopes).empty?
|
|
122
|
+
doc
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Map usage_policy onto Content Signals tokens. `search` stays yes because AI2Web exists to
|
|
126
|
+
# be discoverable; the AI signals are only asserted when the manifest states them, so an
|
|
127
|
+
# unset policy is never reported as a refusal. Nil when no policy is declared.
|
|
128
|
+
def to_content_signals(manifest)
|
|
129
|
+
m = Util.deep_stringify(manifest)
|
|
130
|
+
p = m["usage_policy"]
|
|
131
|
+
return nil unless p.is_a?(Hash) && !p.empty?
|
|
132
|
+
|
|
133
|
+
signals = ["search=yes"]
|
|
134
|
+
signals << "ai-input=#{p["content_reproduction"] ? "yes" : "no"}" if [true, false].include?(p["content_reproduction"])
|
|
135
|
+
signals << "ai-train=#{p["model_training"] ? "yes" : "no"}" if [true, false].include?(p["model_training"])
|
|
136
|
+
signals.join(", ")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# A robots.txt FRAGMENT carrying the usage policy and a pointer to the manifest. Append it to
|
|
140
|
+
# an existing robots.txt; it is never a replacement, and emits no Disallow rules.
|
|
141
|
+
def to_robots_txt(manifest)
|
|
142
|
+
m = Util.deep_stringify(manifest)
|
|
143
|
+
site = m["site"].is_a?(Hash) ? m["site"] : {}
|
|
144
|
+
base = Util.trim_url(site["url"].to_s)
|
|
145
|
+
lines = ["# AI2Web usage policy, projected from #{base}/ai2w", "User-agent: *"]
|
|
146
|
+
signals = to_content_signals(m)
|
|
147
|
+
lines << "Content-Signal: #{signals}" unless signals.nil?
|
|
148
|
+
lines << "# bulk_extraction: false - please use the /ai2w endpoints instead of crawling" if
|
|
149
|
+
m["usage_policy"].is_a?(Hash) && m["usage_policy"]["bulk_extraction"] == false
|
|
150
|
+
lines << "# AI2Web-Manifest: #{base}/ai2w"
|
|
151
|
+
"#{lines.join("\n")}\n"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Value for an HTTP Link header advertising the manifest to non-HTML clients.
|
|
155
|
+
def to_discovery_link_header(manifest)
|
|
156
|
+
m = Util.deep_stringify(manifest)
|
|
157
|
+
site = m["site"].is_a?(Hash) ? m["site"] : {}
|
|
158
|
+
"<#{Util.trim_url(site["url"].to_s)}/ai2w>; rel=\"ai2w\""
|
|
159
|
+
end
|
|
90
160
|
end
|
|
91
161
|
|
|
92
162
|
module_function
|
|
93
163
|
|
|
94
164
|
def to_llms_txt(manifest) = Export.to_llms_txt(manifest)
|
|
95
165
|
def to_agent_json(manifest) = Export.to_agent_json(manifest)
|
|
166
|
+
def to_oauth_protected_resource(manifest) = Export.to_oauth_protected_resource(manifest)
|
|
167
|
+
def to_content_signals(manifest) = Export.to_content_signals(manifest)
|
|
168
|
+
def to_robots_txt(manifest) = Export.to_robots_txt(manifest)
|
|
169
|
+
def to_discovery_link_header(manifest) = Export.to_discovery_link_header(manifest)
|
|
96
170
|
end
|
data/lib/ai2web/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ai2web
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- AI2Web Foundation
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: The Ruby implementation of the AI2Web protocol - describe your website
|
|
14
14
|
once and make it understandable and actionable to any AI agent. Fluent manifest
|