@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.
Files changed (115) hide show
  1. package/README.md +93 -0
  2. package/bin/adgine-geo.js +224 -0
  3. package/package.json +38 -0
  4. package/skills/.env.example +11 -0
  5. package/skills/README.md +247 -0
  6. package/skills/SKILL.md +117 -0
  7. package/skills/VERSION +1 -0
  8. package/skills/adgine-geo-aiagent/SKILL.md +200 -0
  9. package/skills/adgine-geo-aiagent/scripts/_client.py +341 -0
  10. package/skills/adgine-geo-aiagent/scripts/bot_traffic.py +278 -0
  11. package/skills/adgine-geo-aiagent/scripts/human_traffic.py +357 -0
  12. package/skills/adgine-geo-aiagent/scripts/page_analytics.py +317 -0
  13. package/skills/adgine-geo-aiagent/scripts/page_detail.py +273 -0
  14. package/skills/adgine-geo-analytics/API.md +89 -0
  15. package/skills/adgine-geo-analytics/SKILL.md +191 -0
  16. package/skills/adgine-geo-analytics/scripts/_client.py +341 -0
  17. package/skills/adgine-geo-analytics/scripts/get_overview.py +129 -0
  18. package/skills/adgine-geo-billing/SKILL.md +118 -0
  19. package/skills/adgine-geo-billing/scripts/_client.py +341 -0
  20. package/skills/adgine-geo-billing/scripts/get_credits.py +51 -0
  21. package/skills/adgine-geo-billing/scripts/get_credits_pricing.py +52 -0
  22. package/skills/adgine-geo-billing/scripts/get_subscription.py +48 -0
  23. package/skills/adgine-geo-billing/scripts/list_plans.py +66 -0
  24. package/skills/adgine-geo-brand/SKILL.md +193 -0
  25. package/skills/adgine-geo-brand/WORKFLOW.md +66 -0
  26. package/skills/adgine-geo-brand/scripts/_client.py +341 -0
  27. package/skills/adgine-geo-brand/scripts/generate_brand.py +95 -0
  28. package/skills/adgine-geo-brand/scripts/get_brand.py +67 -0
  29. package/skills/adgine-geo-brand/scripts/list_jobs.py +153 -0
  30. package/skills/adgine-geo-brand/scripts/update_brand.py +61 -0
  31. package/skills/adgine-geo-citation/SKILL.md +220 -0
  32. package/skills/adgine-geo-citation/scripts/_client.py +341 -0
  33. package/skills/adgine-geo-citation/scripts/create_tests.py +62 -0
  34. package/skills/adgine-geo-citation/scripts/get_aggregate.py +108 -0
  35. package/skills/adgine-geo-citation/scripts/get_results.py +179 -0
  36. package/skills/adgine-geo-content/SKILL.md +224 -0
  37. package/skills/adgine-geo-content/WORKFLOW.md +100 -0
  38. package/skills/adgine-geo-content/scripts/_client.py +341 -0
  39. package/skills/adgine-geo-content/scripts/generate_article.py +108 -0
  40. package/skills/adgine-geo-content/scripts/generate_outline.py +113 -0
  41. package/skills/adgine-geo-content/scripts/generate_titles.py +51 -0
  42. package/skills/adgine-geo-content/scripts/list_content.py +65 -0
  43. package/skills/adgine-geo-content/scripts/manage_content.py +90 -0
  44. package/skills/adgine-geo-content/scripts/manage_jobs.py +184 -0
  45. package/skills/adgine-geo-dashboard/SKILL.md +181 -0
  46. package/skills/adgine-geo-dashboard/scripts/_client.py +341 -0
  47. package/skills/adgine-geo-dashboard/scripts/check_integrations.py +139 -0
  48. package/skills/adgine-geo-dashboard/scripts/get_overview.py +155 -0
  49. package/skills/adgine-geo-dashboard/scripts/get_visibility_overview.py +93 -0
  50. package/skills/adgine-geo-docs/SKILL.md +60 -0
  51. package/skills/adgine-geo-domains/SKILL.md +223 -0
  52. package/skills/adgine-geo-domains/scripts/_client.py +341 -0
  53. package/skills/adgine-geo-domains/scripts/get_domain.py +75 -0
  54. package/skills/adgine-geo-domains/scripts/list_domains.py +66 -0
  55. package/skills/adgine-geo-domains/scripts/search_domains.py +85 -0
  56. package/skills/adgine-geo-integrations/SKILL.md +188 -0
  57. package/skills/adgine-geo-integrations/scripts/_client.py +341 -0
  58. package/skills/adgine-geo-integrations/scripts/cloudflare_connect.py +155 -0
  59. package/skills/adgine-geo-integrations/scripts/cloudflare_worker.py +212 -0
  60. package/skills/adgine-geo-integrations/scripts/ga4_data.py +192 -0
  61. package/skills/adgine-geo-integrations/scripts/ga4_setup.py +120 -0
  62. package/skills/adgine-geo-opportunities/SKILL.md +162 -0
  63. package/skills/adgine-geo-opportunities/scripts/_client.py +341 -0
  64. package/skills/adgine-geo-opportunities/scripts/get_opportunity.py +90 -0
  65. package/skills/adgine-geo-opportunities/scripts/list_opportunities.py +92 -0
  66. package/skills/adgine-geo-performance/SKILL.md +177 -0
  67. package/skills/adgine-geo-performance/scripts/_client.py +341 -0
  68. package/skills/adgine-geo-performance/scripts/analyze_page.py +100 -0
  69. package/skills/adgine-geo-projects/SKILL.md +279 -0
  70. package/skills/adgine-geo-projects/scripts/_client.py +341 -0
  71. package/skills/adgine-geo-projects/scripts/check_auth.py +45 -0
  72. package/skills/adgine-geo-projects/scripts/list_projects.py +47 -0
  73. package/skills/adgine-geo-projects/scripts/manage_competitors.py +122 -0
  74. package/skills/adgine-geo-projects/scripts/manage_project.py +88 -0
  75. package/skills/adgine-geo-saas/SKILL.md +144 -0
  76. package/skills/adgine-geo-saas/scripts/_client.py +341 -0
  77. package/skills/adgine-geo-saas/scripts/check_domain.py +43 -0
  78. package/skills/adgine-geo-saas/scripts/create_website.py +56 -0
  79. package/skills/adgine-geo-saas/scripts/get_task.py +94 -0
  80. package/skills/adgine-geo-site-audit/README.md +281 -0
  81. package/skills/adgine-geo-site-audit/SKILL.md +449 -0
  82. package/skills/adgine-geo-site-audit/requirements.txt +5 -0
  83. package/skills/adgine-geo-site-audit/scripts/_client.py +341 -0
  84. package/skills/adgine-geo-site-audit/scripts/_geo_notice.py +55 -0
  85. package/skills/adgine-geo-site-audit/scripts/export_skill_package.py +197 -0
  86. package/skills/adgine-geo-site-audit/scripts/geo_collect.py +2443 -0
  87. package/skills/adgine-geo-site-audit/scripts/geo_score.py +490 -0
  88. package/skills/adgine-geo-site-audit/scripts/geo_timing.py +399 -0
  89. package/skills/adgine-geo-site-audit/scripts/geo_visibility.py +718 -0
  90. package/skills/adgine-geo-site-audit/scripts/render_report_pdf.py +1502 -0
  91. package/skills/adgine-geo-topics/SKILL.md +232 -0
  92. package/skills/adgine-geo-topics/scripts/_client.py +341 -0
  93. package/skills/adgine-geo-topics/scripts/generate_prompts.py +140 -0
  94. package/skills/adgine-geo-topics/scripts/manage_prompts.py +153 -0
  95. package/skills/adgine-geo-topics/scripts/manage_topics.py +145 -0
  96. package/skills/adgine-geo-visibility/SKILL.md +168 -0
  97. package/skills/adgine-geo-visibility/scripts/_client.py +341 -0
  98. package/skills/adgine-geo-visibility/scripts/get_execution.py +151 -0
  99. package/skills/adgine-geo-visibility/scripts/get_matrix.py +111 -0
  100. package/skills/adgine-geo-visibility/scripts/get_prompt_metrics.py +104 -0
  101. package/skills/adgine-geo-visibility/scripts/get_topic_metrics.py +201 -0
  102. package/skills/adgine-geo-visibility/scripts/get_visibility.py +166 -0
  103. package/skills/adgine-geo-wordpress/SKILL.md +151 -0
  104. package/skills/adgine-geo-wordpress/scripts/_client.py +341 -0
  105. package/skills/adgine-geo-wordpress/scripts/list_publishable.py +62 -0
  106. package/skills/adgine-geo-wordpress/scripts/manage_credentials.py +139 -0
  107. package/skills/adgine-geo-wordpress/scripts/manage_publishes.py +108 -0
  108. package/skills/adgine-geo-wordpress/scripts/publish.py +79 -0
  109. package/skills/scripts/check_version.py +290 -0
  110. package/skills/setup.py +248 -0
  111. package/src/config.js +126 -0
  112. package/src/doctor.js +137 -0
  113. package/src/install.js +90 -0
  114. package/src/manifest.js +99 -0
  115. 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}` | 单条域名注册记录详情 |