@adgine/geo-cli 1.2.8
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.
- package/README.md +93 -0
- package/bin/adgine-geo.js +224 -0
- package/package.json +38 -0
- package/skills/.env.example +11 -0
- package/skills/README.md +247 -0
- package/skills/SKILL.md +117 -0
- package/skills/VERSION +1 -0
- package/skills/adgine-geo-aiagent/SKILL.md +200 -0
- package/skills/adgine-geo-aiagent/scripts/_client.py +341 -0
- package/skills/adgine-geo-aiagent/scripts/bot_traffic.py +278 -0
- package/skills/adgine-geo-aiagent/scripts/human_traffic.py +357 -0
- package/skills/adgine-geo-aiagent/scripts/page_analytics.py +317 -0
- package/skills/adgine-geo-aiagent/scripts/page_detail.py +273 -0
- package/skills/adgine-geo-analytics/API.md +89 -0
- package/skills/adgine-geo-analytics/SKILL.md +191 -0
- package/skills/adgine-geo-analytics/scripts/_client.py +341 -0
- package/skills/adgine-geo-analytics/scripts/get_overview.py +129 -0
- package/skills/adgine-geo-billing/SKILL.md +118 -0
- package/skills/adgine-geo-billing/scripts/_client.py +341 -0
- package/skills/adgine-geo-billing/scripts/get_credits.py +51 -0
- package/skills/adgine-geo-billing/scripts/get_credits_pricing.py +52 -0
- package/skills/adgine-geo-billing/scripts/get_subscription.py +48 -0
- package/skills/adgine-geo-billing/scripts/list_plans.py +66 -0
- package/skills/adgine-geo-brand/SKILL.md +193 -0
- package/skills/adgine-geo-brand/WORKFLOW.md +66 -0
- package/skills/adgine-geo-brand/scripts/_client.py +341 -0
- package/skills/adgine-geo-brand/scripts/generate_brand.py +95 -0
- package/skills/adgine-geo-brand/scripts/get_brand.py +67 -0
- package/skills/adgine-geo-brand/scripts/list_jobs.py +153 -0
- package/skills/adgine-geo-brand/scripts/update_brand.py +61 -0
- package/skills/adgine-geo-citation/SKILL.md +220 -0
- package/skills/adgine-geo-citation/scripts/_client.py +341 -0
- package/skills/adgine-geo-citation/scripts/create_tests.py +62 -0
- package/skills/adgine-geo-citation/scripts/get_aggregate.py +108 -0
- package/skills/adgine-geo-citation/scripts/get_results.py +179 -0
- package/skills/adgine-geo-content/SKILL.md +224 -0
- package/skills/adgine-geo-content/WORKFLOW.md +100 -0
- package/skills/adgine-geo-content/scripts/_client.py +341 -0
- package/skills/adgine-geo-content/scripts/generate_article.py +108 -0
- package/skills/adgine-geo-content/scripts/generate_outline.py +113 -0
- package/skills/adgine-geo-content/scripts/generate_titles.py +51 -0
- package/skills/adgine-geo-content/scripts/list_content.py +65 -0
- package/skills/adgine-geo-content/scripts/manage_content.py +90 -0
- package/skills/adgine-geo-content/scripts/manage_jobs.py +184 -0
- package/skills/adgine-geo-dashboard/SKILL.md +181 -0
- package/skills/adgine-geo-dashboard/scripts/_client.py +341 -0
- package/skills/adgine-geo-dashboard/scripts/check_integrations.py +139 -0
- package/skills/adgine-geo-dashboard/scripts/get_overview.py +155 -0
- package/skills/adgine-geo-dashboard/scripts/get_visibility_overview.py +93 -0
- package/skills/adgine-geo-docs/SKILL.md +60 -0
- package/skills/adgine-geo-domains/SKILL.md +223 -0
- package/skills/adgine-geo-domains/scripts/_client.py +341 -0
- package/skills/adgine-geo-domains/scripts/get_domain.py +75 -0
- package/skills/adgine-geo-domains/scripts/list_domains.py +66 -0
- package/skills/adgine-geo-domains/scripts/search_domains.py +85 -0
- package/skills/adgine-geo-integrations/SKILL.md +188 -0
- package/skills/adgine-geo-integrations/scripts/_client.py +341 -0
- package/skills/adgine-geo-integrations/scripts/cloudflare_connect.py +155 -0
- package/skills/adgine-geo-integrations/scripts/cloudflare_worker.py +212 -0
- package/skills/adgine-geo-integrations/scripts/ga4_data.py +192 -0
- package/skills/adgine-geo-integrations/scripts/ga4_setup.py +120 -0
- package/skills/adgine-geo-opportunities/SKILL.md +162 -0
- package/skills/adgine-geo-opportunities/scripts/_client.py +341 -0
- package/skills/adgine-geo-opportunities/scripts/get_opportunity.py +90 -0
- package/skills/adgine-geo-opportunities/scripts/list_opportunities.py +92 -0
- package/skills/adgine-geo-performance/SKILL.md +177 -0
- package/skills/adgine-geo-performance/scripts/_client.py +341 -0
- package/skills/adgine-geo-performance/scripts/analyze_page.py +100 -0
- package/skills/adgine-geo-projects/SKILL.md +279 -0
- package/skills/adgine-geo-projects/scripts/_client.py +341 -0
- package/skills/adgine-geo-projects/scripts/check_auth.py +45 -0
- package/skills/adgine-geo-projects/scripts/list_projects.py +47 -0
- package/skills/adgine-geo-projects/scripts/manage_competitors.py +122 -0
- package/skills/adgine-geo-projects/scripts/manage_project.py +88 -0
- package/skills/adgine-geo-saas/SKILL.md +144 -0
- package/skills/adgine-geo-saas/scripts/_client.py +341 -0
- package/skills/adgine-geo-saas/scripts/check_domain.py +43 -0
- package/skills/adgine-geo-saas/scripts/create_website.py +56 -0
- package/skills/adgine-geo-saas/scripts/get_task.py +94 -0
- package/skills/adgine-geo-site-audit/README.md +281 -0
- package/skills/adgine-geo-site-audit/SKILL.md +449 -0
- package/skills/adgine-geo-site-audit/requirements.txt +5 -0
- package/skills/adgine-geo-site-audit/scripts/_client.py +341 -0
- package/skills/adgine-geo-site-audit/scripts/_geo_notice.py +55 -0
- package/skills/adgine-geo-site-audit/scripts/export_skill_package.py +197 -0
- package/skills/adgine-geo-site-audit/scripts/geo_collect.py +2443 -0
- package/skills/adgine-geo-site-audit/scripts/geo_score.py +490 -0
- package/skills/adgine-geo-site-audit/scripts/geo_timing.py +399 -0
- package/skills/adgine-geo-site-audit/scripts/geo_visibility.py +718 -0
- package/skills/adgine-geo-site-audit/scripts/render_report_pdf.py +1502 -0
- package/skills/adgine-geo-topics/SKILL.md +232 -0
- package/skills/adgine-geo-topics/scripts/_client.py +341 -0
- package/skills/adgine-geo-topics/scripts/generate_prompts.py +140 -0
- package/skills/adgine-geo-topics/scripts/manage_prompts.py +153 -0
- package/skills/adgine-geo-topics/scripts/manage_topics.py +145 -0
- package/skills/adgine-geo-visibility/SKILL.md +168 -0
- package/skills/adgine-geo-visibility/scripts/_client.py +341 -0
- package/skills/adgine-geo-visibility/scripts/get_execution.py +151 -0
- package/skills/adgine-geo-visibility/scripts/get_matrix.py +111 -0
- package/skills/adgine-geo-visibility/scripts/get_prompt_metrics.py +104 -0
- package/skills/adgine-geo-visibility/scripts/get_topic_metrics.py +201 -0
- package/skills/adgine-geo-visibility/scripts/get_visibility.py +166 -0
- package/skills/adgine-geo-wordpress/SKILL.md +151 -0
- package/skills/adgine-geo-wordpress/scripts/_client.py +341 -0
- package/skills/adgine-geo-wordpress/scripts/list_publishable.py +62 -0
- package/skills/adgine-geo-wordpress/scripts/manage_credentials.py +139 -0
- package/skills/adgine-geo-wordpress/scripts/manage_publishes.py +108 -0
- package/skills/adgine-geo-wordpress/scripts/publish.py +79 -0
- package/skills/scripts/check_version.py +290 -0
- package/skills/setup.py +248 -0
- package/src/config.js +126 -0
- package/src/doctor.js +137 -0
- package/src/install.js +90 -0
- package/src/manifest.js +99 -0
- package/src/runner.js +159 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Fetch the project dashboard overview snapshot.
|
|
3
|
+
|
|
4
|
+
Returns the aggregate dashboard metrics for a project (visibility, prompts,
|
|
5
|
+
topics, test counts, etc.) for the requested period.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python3 scripts/get_overview.py [--project-id <id>] [--period 30d] [--json]
|
|
9
|
+
"""
|
|
10
|
+
import sys
|
|
11
|
+
import os
|
|
12
|
+
import argparse
|
|
13
|
+
|
|
14
|
+
sys.path.insert(0, os.path.dirname(__file__))
|
|
15
|
+
from _client import (
|
|
16
|
+
get_api_config, get_project_id, api_get, extract_data, print_json, fmt_change,
|
|
17
|
+
pad,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _scalar(obj, key, default=None):
|
|
22
|
+
"""Extract a scalar that may be wrapped in {value, change} or returned plain."""
|
|
23
|
+
if not isinstance(obj, dict):
|
|
24
|
+
return default
|
|
25
|
+
v = obj.get(key)
|
|
26
|
+
if isinstance(v, dict) and "value" in v:
|
|
27
|
+
return v.get("value", default)
|
|
28
|
+
return v if v is not None else default
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _delta(obj, key):
|
|
32
|
+
"""Extract the change delta from a {value, change} wrapper, or return None."""
|
|
33
|
+
if not isinstance(obj, dict):
|
|
34
|
+
return None
|
|
35
|
+
v = obj.get(key)
|
|
36
|
+
if isinstance(v, dict):
|
|
37
|
+
return v.get("change")
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _fmt_num(n):
|
|
42
|
+
if n is None:
|
|
43
|
+
return "--"
|
|
44
|
+
try:
|
|
45
|
+
f = float(n)
|
|
46
|
+
except (TypeError, ValueError):
|
|
47
|
+
return str(n)
|
|
48
|
+
if f == int(f):
|
|
49
|
+
return f"{int(f):,}"
|
|
50
|
+
return f"{f:,.1f}"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def main():
|
|
54
|
+
parser = argparse.ArgumentParser(description="Fetch GEO project dashboard overview")
|
|
55
|
+
parser.add_argument("--project-id", help="Project ID (or set GEO_PROJECT_ID env var)")
|
|
56
|
+
parser.add_argument("--period", default="30d", choices=["7d", "14d", "30d", "90d"],
|
|
57
|
+
help="Time period (default: 30d)")
|
|
58
|
+
parser.add_argument("--json", action="store_true", help="Output raw JSON")
|
|
59
|
+
args = parser.parse_args()
|
|
60
|
+
|
|
61
|
+
key, base = get_api_config()
|
|
62
|
+
pid = get_project_id(args.project_id)
|
|
63
|
+
|
|
64
|
+
result = api_get(
|
|
65
|
+
f"/api/projects/{pid}/dashboard/overview",
|
|
66
|
+
key, base,
|
|
67
|
+
params={"period": args.period},
|
|
68
|
+
)
|
|
69
|
+
data = extract_data(result) or {}
|
|
70
|
+
|
|
71
|
+
if args.json:
|
|
72
|
+
print_json(data)
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
period = data.get("period", args.period)
|
|
76
|
+
dr = data.get("date_range") or {}
|
|
77
|
+
start = dr.get("start", "--")
|
|
78
|
+
end = dr.get("end", "--")
|
|
79
|
+
|
|
80
|
+
print(f"Dashboard Overview — {start} to {end} ({period})")
|
|
81
|
+
print(f"Project: {pid}")
|
|
82
|
+
print()
|
|
83
|
+
|
|
84
|
+
# ── Snapshot metrics ──────────────────────────────────────────────────
|
|
85
|
+
# The dashboard/overview payload aggregates several top-level metric
|
|
86
|
+
# groups. We render whichever ones are present, with graceful fallback.
|
|
87
|
+
metric_keys = [
|
|
88
|
+
("visibility_score", "Visibility Score"),
|
|
89
|
+
("prompts_total", "Prompts (total)"),
|
|
90
|
+
("prompts_tested", "Prompts tested"),
|
|
91
|
+
("topics_total", "Topics"),
|
|
92
|
+
("tests_total", "Tests run"),
|
|
93
|
+
("citations_total", "Citations"),
|
|
94
|
+
("articles_total", "Articles"),
|
|
95
|
+
("ai_referrals", "AI referrals"),
|
|
96
|
+
]
|
|
97
|
+
rows = []
|
|
98
|
+
for k, label in metric_keys:
|
|
99
|
+
if k in data:
|
|
100
|
+
rows.append((label, _scalar(data, k), _delta(data, k)))
|
|
101
|
+
|
|
102
|
+
if rows:
|
|
103
|
+
print("Snapshot")
|
|
104
|
+
print("```")
|
|
105
|
+
print("┌────────────────────────┬──────────┬──────────┐")
|
|
106
|
+
print("│ Metric │ Value │ vs Prev │")
|
|
107
|
+
print("├────────────────────────┼──────────┼──────────┤")
|
|
108
|
+
for label, val, change in rows:
|
|
109
|
+
print(f"│ {pad(label, 22)} │ {_fmt_num(val):>8} │ {fmt_change(change):>8} │")
|
|
110
|
+
print("└────────────────────────┴──────────┴──────────┘")
|
|
111
|
+
print("```")
|
|
112
|
+
print()
|
|
113
|
+
|
|
114
|
+
# ── Top lists (if present) ────────────────────────────────────────────
|
|
115
|
+
for list_key, title, name_field, value_field, value_label in [
|
|
116
|
+
("top_topics", "Top Topics", "name", "score", "Score"),
|
|
117
|
+
("top_prompts", "Top Prompts", "text", "score", "Score"),
|
|
118
|
+
("recent_tests", "Recent Tests", "prompt", "platform", "Platform"),
|
|
119
|
+
]:
|
|
120
|
+
items = data.get(list_key) or []
|
|
121
|
+
if not items:
|
|
122
|
+
continue
|
|
123
|
+
print(f"{title}")
|
|
124
|
+
print("```")
|
|
125
|
+
print("┌────┬────────────────────────────────────────┬──────────┐")
|
|
126
|
+
print(f"│ # │ {pad('Name', 38)} │ {pad(value_label, 8)} │")
|
|
127
|
+
print("├────┼────────────────────────────────────────┼──────────┤")
|
|
128
|
+
for idx, item in enumerate(items[:5], 1):
|
|
129
|
+
name = str(item.get(name_field, ""))
|
|
130
|
+
value = str(item.get(value_field, ""))
|
|
131
|
+
if len(name) > 38:
|
|
132
|
+
name = name[:37] + "…"
|
|
133
|
+
print(f"│ {idx:>2} │ {pad(name, 38)} │ {pad(value, 8)} │")
|
|
134
|
+
print("└────┴────────────────────────────────────────┴──────────┘")
|
|
135
|
+
print("```")
|
|
136
|
+
print()
|
|
137
|
+
|
|
138
|
+
# ── Fallback: dump unknown top-level keys ─────────────────────────────
|
|
139
|
+
if not rows:
|
|
140
|
+
print("Raw snapshot keys:")
|
|
141
|
+
for k, v in data.items():
|
|
142
|
+
if k in ("period", "date_range"):
|
|
143
|
+
continue
|
|
144
|
+
if isinstance(v, (str, int, float, bool)) or v is None:
|
|
145
|
+
print(f" {k}: {v}")
|
|
146
|
+
elif isinstance(v, list):
|
|
147
|
+
print(f" {k}: list[{len(v)}]")
|
|
148
|
+
elif isinstance(v, dict):
|
|
149
|
+
print(f" {k}: dict({', '.join(v.keys())})")
|
|
150
|
+
print()
|
|
151
|
+
print("Tip: rerun with --json to see the full payload.")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
main()
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Fetch the lightweight 7-day brand visibility snapshot.
|
|
3
|
+
|
|
4
|
+
Returns current visibility score, 7-day daily trend and period-over-period change.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
python3 scripts/get_visibility_overview.py [--project-id <id>] \\
|
|
8
|
+
[--start-date YYYY-MM-DD] [--end-date YYYY-MM-DD] [--json]
|
|
9
|
+
"""
|
|
10
|
+
import sys
|
|
11
|
+
import os
|
|
12
|
+
import argparse
|
|
13
|
+
|
|
14
|
+
sys.path.insert(0, os.path.dirname(__file__))
|
|
15
|
+
from _client import (
|
|
16
|
+
get_api_config, get_project_id, api_get, extract_data, print_json, fmt_change,
|
|
17
|
+
pad,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _fmt_score(n):
|
|
22
|
+
if n is None:
|
|
23
|
+
return "--"
|
|
24
|
+
try:
|
|
25
|
+
return f"{float(n):.1f}"
|
|
26
|
+
except (TypeError, ValueError):
|
|
27
|
+
return str(n)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def main():
|
|
31
|
+
parser = argparse.ArgumentParser(description="Fetch GEO visibility overview")
|
|
32
|
+
parser.add_argument("--project-id", help="Project ID (or set GEO_PROJECT_ID env var)")
|
|
33
|
+
parser.add_argument("--start-date", help="Start date YYYY-MM-DD")
|
|
34
|
+
parser.add_argument("--end-date", help="End date YYYY-MM-DD")
|
|
35
|
+
parser.add_argument("--json", action="store_true", help="Output raw JSON")
|
|
36
|
+
args = parser.parse_args()
|
|
37
|
+
|
|
38
|
+
key, base = get_api_config()
|
|
39
|
+
pid = get_project_id(args.project_id)
|
|
40
|
+
|
|
41
|
+
params = {}
|
|
42
|
+
if args.start_date:
|
|
43
|
+
params["start_date"] = args.start_date
|
|
44
|
+
if args.end_date:
|
|
45
|
+
params["end_date"] = args.end_date
|
|
46
|
+
|
|
47
|
+
result = api_get(
|
|
48
|
+
f"/api/projects/{pid}/dashboard/visibility",
|
|
49
|
+
key, base,
|
|
50
|
+
params=params or None,
|
|
51
|
+
)
|
|
52
|
+
data = extract_data(result) or {}
|
|
53
|
+
|
|
54
|
+
if args.json:
|
|
55
|
+
print_json(data)
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
current = data.get("current_score")
|
|
59
|
+
change = data.get("change") or data.get("score_change")
|
|
60
|
+
trend = data.get("daily_scores") or data.get("trend") or []
|
|
61
|
+
|
|
62
|
+
print(f"Visibility Overview")
|
|
63
|
+
print(f"Project: {pid}")
|
|
64
|
+
print()
|
|
65
|
+
|
|
66
|
+
print("```")
|
|
67
|
+
print("┌────────────────────────┬──────────┐")
|
|
68
|
+
print("│ Metric │ Value │")
|
|
69
|
+
print("├────────────────────────┼──────────┤")
|
|
70
|
+
print(f"│ Current Score │ {_fmt_score(current):>8} │")
|
|
71
|
+
print(f"│ Change vs Prev │ {fmt_change(change):>8} │")
|
|
72
|
+
print("└────────────────────────┴──────────┘")
|
|
73
|
+
print("```")
|
|
74
|
+
print()
|
|
75
|
+
|
|
76
|
+
if trend:
|
|
77
|
+
print("7-Day Trend")
|
|
78
|
+
print("```")
|
|
79
|
+
print("┌────────────┬──────────┐")
|
|
80
|
+
print("│ Date │ Score │")
|
|
81
|
+
print("├────────────┼──────────┤")
|
|
82
|
+
for point in trend[:14]:
|
|
83
|
+
date = str(point.get("date", "--"))[:10]
|
|
84
|
+
score = _fmt_score(point.get("score"))
|
|
85
|
+
print(f"│ {pad(date, 10)} │ {score:>8} │")
|
|
86
|
+
print("└────────────┴──────────┘")
|
|
87
|
+
print("```")
|
|
88
|
+
else:
|
|
89
|
+
print("No daily trend data available for the requested range.")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
main()
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: adgine/geo-docs
|
|
3
|
+
description: Provides the Adgine platform user manual (使用手册). Use when the user asks how to use Adgine, needs help documentation, asks for the user guide, or mentions 使用手册, 帮助文档, 产品说明, user manual, documentation, help guide, how to use, 怎么用, 操作指南, 教程. This skill points to the official Adgine user manual hosted online (PDF). No API key required.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Docs — Adgine 使用手册
|
|
7
|
+
|
|
8
|
+
This skill provides access to the official Adgine platform user manual, hosted online.
|
|
9
|
+
|
|
10
|
+
## No authentication required
|
|
11
|
+
|
|
12
|
+
This skill needs no `GEO_API_KEY`. The manual is hosted at a public URL — the agent
|
|
13
|
+
simply outputs the link (and may fetch the URL when answering specific content questions).
|
|
14
|
+
|
|
15
|
+
## Manual location
|
|
16
|
+
|
|
17
|
+
**Online manual (PDF):** https://docs.adgine.ai/files/Adgine使用手册-v20260531.pdf
|
|
18
|
+
|
|
19
|
+
**Current version:** v20260531 (2025-05-31)
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### When the user asks to view or download the user manual (查看手册 / 下载手册 / 我要手册)
|
|
24
|
+
|
|
25
|
+
**必须输出 PDF 的 Markdown 链接,让用户看到可点击的下载/预览按钮:**
|
|
26
|
+
|
|
27
|
+
> ⚠️ **CRITICAL — 必须输出可点击的链接:**
|
|
28
|
+
> 当用户说 "查看使用手册", "下载手册", "给我手册", "我要用户手册", "view manual", "download manual", "打开手册" 时:
|
|
29
|
+
> 1. **必须** 输出 Markdown 格式的链接,让用户可以直接点击下载或预览
|
|
30
|
+
> 2. **禁止** 仅输出纯文本 URL 让用户复制粘贴
|
|
31
|
+
>
|
|
32
|
+
> 正确做法 — 输出指向在线手册的 Markdown 链接:
|
|
33
|
+
> ```markdown
|
|
34
|
+
> [📄 Adgine使用手册-v20260531.pdf](https://docs.adgine.ai/files/Adgine使用手册-v20260531.pdf)
|
|
35
|
+
> ```
|
|
36
|
+
|
|
37
|
+
### When the user asks a specific question about how to use Adgine
|
|
38
|
+
|
|
39
|
+
1. **Fetch** the online manual at `https://docs.adgine.ai/files/Adgine使用手册-v20260531.pdf` to find relevant content.
|
|
40
|
+
2. **Answer** the user's question based on the manual content.
|
|
41
|
+
3. **Reference** the PDF link so the user can view the full formatted manual.
|
|
42
|
+
|
|
43
|
+
## Output Format
|
|
44
|
+
|
|
45
|
+
### For view/download requests
|
|
46
|
+
|
|
47
|
+
**直接输出以下内容(Markdown 链接 + 说明):**
|
|
48
|
+
|
|
49
|
+
> 📄 **Adgine 使用手册 (v20260531)**
|
|
50
|
+
>
|
|
51
|
+
> [点击下载/预览 PDF](https://docs.adgine.ai/files/Adgine使用手册-v20260531.pdf)
|
|
52
|
+
>
|
|
53
|
+
> 这是 Adgine 平台的完整使用手册,包含所有功能的详细操作指南。
|
|
54
|
+
|
|
55
|
+
### For content questions
|
|
56
|
+
|
|
57
|
+
- Provide a clear, concise answer based on the manual content
|
|
58
|
+
- Quote relevant sections when helpful
|
|
59
|
+
- Mention that this comes from the official Adgine 使用手册 (v20260531)
|
|
60
|
+
- If the user wants more detail, suggest they review the full PDF manual at the link above
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: adgine/geo-domains
|
|
3
|
+
description: Search available domains by keyword, list registered domains, and view domain registration details. Use when the user asks about domain availability, domain registration, domain search, 域名搜索, 域名注册, 查询域名, 我的域名, 域名状态. Read-only — does not register domains directly (direct users to the web UI for registration).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Domains
|
|
7
|
+
|
|
8
|
+
Read-only access to domain search and your registered domains. Use this skill when the
|
|
9
|
+
user asks "search domains for my brand" / "is example.com available?" / "show my
|
|
10
|
+
domains" / "域名搜索" / "查询域名" / "我的域名" / "这个域名能注册吗".
|
|
11
|
+
|
|
12
|
+
**Domain registration itself is done via the web UI** — after finding an available
|
|
13
|
+
domain, this skill provides a clickable registration link.
|
|
14
|
+
|
|
15
|
+
## Output rules — IDs (apply to every reply)
|
|
16
|
+
|
|
17
|
+
These rules apply to **every list, table, and confirmation message** in this skill.
|
|
18
|
+
Their goal: keep user-facing output friendly while preserving the IDs the agent needs
|
|
19
|
+
internally.
|
|
20
|
+
|
|
21
|
+
1. **Lists & tables — never show raw UUIDs in cells.** Use a 1-based `#` index column
|
|
22
|
+
instead. Keep a private mental mapping of `#N → actual UUID` so that follow-up
|
|
23
|
+
commands like *"show details of #3"* resolve to the right entity.
|
|
24
|
+
- Index numbers restart from 1 in each new list — they are not stable across calls.
|
|
25
|
+
|
|
26
|
+
2. **Single-item operations — prefer a human name over an ID.**
|
|
27
|
+
- ✅ *"Domain **example.com** — status: Active"*
|
|
28
|
+
- ❌ *"Domain `a4305b57-...` — status: Active"*
|
|
29
|
+
|
|
30
|
+
3. **Always exception: `--json` mode.** When the user passes `--json` to a script or
|
|
31
|
+
explicitly asks for raw JSON / debug output, print the script output verbatim — do
|
|
32
|
+
not strip IDs.
|
|
33
|
+
|
|
34
|
+
4. **Internally, the agent still uses full UUIDs** for every API call (e.g.
|
|
35
|
+
`get_domain.py <domain_id>`). The display rules only affect what is shown back to
|
|
36
|
+
the user.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Step 1: Make sure GEO_API_KEY is configured
|
|
41
|
+
|
|
42
|
+
Scripts auto-load `GEO_API_KEY` from `<skills-root>/.env` on import — **no `export`
|
|
43
|
+
needed, no shell restart needed**. To check the configuration, run any script (it prints
|
|
44
|
+
the exact `.env` path if the key is missing).
|
|
45
|
+
|
|
46
|
+
- ✅ Key already in `<skills-root>/.env` → proceed.
|
|
47
|
+
- ❌ Key missing, or user just gave you a new key → go to the **adgine-geo-projects**
|
|
48
|
+
skill, **Step 0**, which runs `python3 <skills-root>/setup.py <KEY>` to write the key
|
|
49
|
+
into the correct `.env` file. **Never** write the key to `~/.zshrc`, `~/.bashrc`,
|
|
50
|
+
Hermes global config, or any user-secrets store.
|
|
51
|
+
|
|
52
|
+
> ⚠️ **IMPORTANT:** In all shell/exec commands, always reference the key as
|
|
53
|
+
> `$GEO_API_KEY` (the environment variable). Never hardcode the literal value.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Scripts
|
|
58
|
+
|
|
59
|
+
### Search available domains by keyword
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python3 scripts/search_domains.py <keyword> [--limit 20] [--json]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Searches for candidate domains matching the keyword. Returns availability status
|
|
66
|
+
(`available` / `taken` / `unsupported`), pricing (registration + renewal, including
|
|
67
|
+
service fees), and tier information.
|
|
68
|
+
|
|
69
|
+
**For available domains**, the script outputs a `## 马上注册` section at the end with
|
|
70
|
+
plain-text registration URLs in the format:
|
|
71
|
+
`https://platform.adgine.ai/domains/contact?domain={domain_name}`
|
|
72
|
+
|
|
73
|
+
> ⚠️ **YOU MUST include the full `## 马上注册` section verbatim in your reply.**
|
|
74
|
+
> Do NOT omit, summarise, or reformat this section. The user needs these URLs to
|
|
75
|
+
> register a domain. Simply copy-paste the entire section from the script output.
|
|
76
|
+
|
|
77
|
+
Already-registered or unsupported domains do not show a registration link.
|
|
78
|
+
|
|
79
|
+
### List my registered domains
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python3 scripts/list_domains.py [--json]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Returns all domains registered by the current user, with status, expiration date,
|
|
86
|
+
auto-renew setting, and DNS status.
|
|
87
|
+
|
|
88
|
+
### Get domain registration details
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python3 scripts/get_domain.py <domain_id> [--json]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Returns full details for a specific domain registration: Cloudflare state, Zone ID,
|
|
95
|
+
pricing, DNS configuration status, and any error messages.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Agent Output Format
|
|
100
|
+
|
|
101
|
+
Run `search_domains.py <keyword>` (no `--json`). The script output uses a structured
|
|
102
|
+
plain-text format with labelled fields — parse it and render the results as described
|
|
103
|
+
below.
|
|
104
|
+
|
|
105
|
+
### Script output format
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
DOMAIN_SEARCH_RESULTS keyword=<kw>
|
|
109
|
+
|
|
110
|
+
TAKEN_DOMAINS count=N
|
|
111
|
+
TAKEN <name>
|
|
112
|
+
...
|
|
113
|
+
|
|
114
|
+
AVAILABLE_DOMAINS count=N
|
|
115
|
+
AVAILABLE name=<name> price=<price> renewal=<renewal> register_url=<url>
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
UNSUPPORTED_DOMAINS count=N
|
|
119
|
+
UNSUPPORTED <name>
|
|
120
|
+
...
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### How to render the results
|
|
124
|
+
|
|
125
|
+
**⚠️ MANDATORY RULE: every `AVAILABLE` domain MUST be rendered with a clickable
|
|
126
|
+
"[马上注册](register_url)" link. No exceptions. If a domain is available and you do
|
|
127
|
+
not show its registration link, the user cannot register it.**
|
|
128
|
+
|
|
129
|
+
Use this exact structure:
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
**❌ 已注册域名**
|
|
134
|
+
|
|
135
|
+
| 域名 | 状态 |
|
|
136
|
+
|------|------|
|
|
137
|
+
| mybrand.com | ❌ 已注册 |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
**🏆 推荐首选** — pick the `.com` from the AVAILABLE list (or the first available if no `.com`)
|
|
142
|
+
|
|
143
|
+
| 域名 | 年费 | 续费 | |
|
|
144
|
+
|------|------|------|---|
|
|
145
|
+
| **mybrand.com** | $11.51 | $11.51/yr | [马上注册](https://platform.adgine.ai/domains/contact?domain=mybrand.com) |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
**📋 其他可注册域名**
|
|
150
|
+
|
|
151
|
+
| # | 域名 | 年费 | 续费 | |
|
|
152
|
+
|---|------|------|------|---|
|
|
153
|
+
| 2 | mybrand.net | $13.05 | $13.05/yr | [马上注册](https://platform.adgine.ai/domains/contact?domain=mybrand.net) |
|
|
154
|
+
| 3 | mybrand.org | $9.35 | $12.32/yr | [马上注册](https://platform.adgine.ai/domains/contact?domain=mybrand.org) |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
**💡 建议**
|
|
159
|
+
|
|
160
|
+
推荐优先注册 `.com`。所有可注册域名:
|
|
161
|
+
|
|
162
|
+
- [马上注册 mybrand.com](https://platform.adgine.ai/domains/contact?domain=mybrand.com)
|
|
163
|
+
- [马上注册 mybrand.net](https://platform.adgine.ai/domains/contact?domain=mybrand.net)
|
|
164
|
+
- [马上注册 mybrand.org](https://platform.adgine.ai/domains/contact?domain=mybrand.org)
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
The `register_url` value from the script output is the exact URL to use in the
|
|
169
|
+
`[马上注册](URL)` links. Do not construct it yourself — copy it directly from the
|
|
170
|
+
`register_url=` field in the script output.
|
|
171
|
+
|
|
172
|
+
> 🌐 **我的域名**
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
┌────┬──────────────────────┬──────────┬──────────────────────┬──────────┬──────────┐
|
|
176
|
+
│ # │ Domain │ Status │ Expires │ Renew │ DNS │
|
|
177
|
+
├────┼──────────────────────┼──────────┼──────────────────────┼──────────┼──────────┤
|
|
178
|
+
│ 1 │ mybrand.com │ Active │ 2027-06-16 │ Auto │ OK │
|
|
179
|
+
│ 2 │ another-site.io │ Pending │ -- │ Auto │ Pending │
|
|
180
|
+
└────┴──────────────────────┴──────────┴──────────────────────┴──────────┴──────────┘
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### get_domain.py
|
|
184
|
+
|
|
185
|
+
> 🌐 **Domain: mybrand.com**
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
┌────────────────────┬──────────────────────────────────┐
|
|
189
|
+
│ Field │ Value │
|
|
190
|
+
├────────────────────┼──────────────────────────────────┤
|
|
191
|
+
│ Status │ Active │
|
|
192
|
+
│ Cloudflare State │ registered │
|
|
193
|
+
│ Zone ID │ abc123... │
|
|
194
|
+
│ Price │ $12.99 USD │
|
|
195
|
+
│ Expires │ 2027-06-16 │
|
|
196
|
+
│ Auto Renew │ Yes │
|
|
197
|
+
│ DNS Status │ configured │
|
|
198
|
+
│ Created │ 2026-06-16T10:00:00Z │
|
|
199
|
+
└────────────────────┴──────────────────────────────────┘
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Registration Flow
|
|
205
|
+
|
|
206
|
+
When the user has identified a domain they want to register, **do not attempt to
|
|
207
|
+
register via API**. Instead, present the clickable registration link:
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
[注册 {domain_name}](https://platform.adgine.ai/domains/contact?domain={domain_name})
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The user will complete the registration form (contact info, Stripe payment) on the web.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Related endpoints
|
|
218
|
+
|
|
219
|
+
| Method | Path | Description |
|
|
220
|
+
|--------|------|-------------|
|
|
221
|
+
| GET | `/api/domains/search` | 按关键词搜索候选域名 |
|
|
222
|
+
| GET | `/api/domains` | 当前用户的域名注册记录列表 |
|
|
223
|
+
| GET | `/api/domains/{domain_id}` | 单条域名注册记录详情 |
|