Install
openclaw skills install @pokemummaster/cloud-game天翼云游戏平台的搜索、推荐与启动技能。当用户明确表达游戏相关意图时使用,包括:想玩游戏、打开游戏、搜索游戏、推荐游戏、找某类游戏、询问某个游戏或游戏类型。即使用户没有提到天翼云游戏平台,只要意图明确与游戏有关,也应触发此技能。不要在纯泛意图下触发,例如用户只说"无聊了""有什么好玩的"且未提到游戏。
openclaw skills install @pokemummaster/cloud-game通过自然语言帮用户在天翼云游戏平台搜索游戏、推荐游戏,并在确认后快速打开游戏页面。
触发本技能:
不要触发本技能:
目标是让用户感觉“说一句就能玩”,不要暴露内部工具、接口、缓存、解析等过程。
只允许在这些节点输出:
严禁输出这类内部过程话术:
缓存、接口、终端、文件读取、URL 清理都属于内部实现,不要向用户描述。即使正在执行缓存门禁,也只能输出用户可见提示,例如:
🔍 正在帮你搜「关键词」,稍等一下下~
或缓存命中时:
🔍 刚搜过「关键词」,直接拿结果给你,不用再等~
gameList 和 search。用户明显给出具体游戏名时,优先使用 gameList API。
示例:
处理规则:
用户描述类型、玩法、题材、风格时,使用 search API。
示例:
处理规则:
当用户输入既像游戏名又像类型描述时,并发请求 gameList API 和 search API。
示例:
处理规则:
如果上一轮已经展示推荐列表,并保存了候选项,本轮用户说“第 1 个”“第二款”“就这个”“打开它”时:
缓存未命中时:
🔍 正在帮你搜「关键词」,稍等一下下~
💡 小贴士:{随机小贴士}
缓存命中时:
🔍 刚搜过「关键词」,直接拿结果给你,不用再等~
小贴士从下面随机选择,避免连续两次相同:
> 🎮 **游戏名称** 评分文案
>
> *一句话简介,不超过 50 字*
>
> 🚀 已经帮你找到啦,马上打开~
打开成功后:
✅ 搞定!**游戏名称** 已经在浏览器里等着你了,冲吧!🎮
汇总文案:
🎯 帮你找到了 N 款,来看看有没有对味的~🎯 目前搜到 N 款,先看看合不合你胃口~列表模板:
1. 🥇 **游戏名称** 评分文案
*一句话简介,不超过 50 字*
2. 🥈 **游戏名称** 评分文案
*一句话简介,不超过 50 字*
列表结尾:
挑中哪个了?跟我说序号或游戏名就行~
展示列表后,必须在会话状态中保留候选项的 title、url、rate、summary,用于下一轮选择。
调用 API 前必须先检查本地缓存,减少重复请求和等待。缓存不是可选优化,而是 API 调用的前置门禁。
强制规则:
gameList API 或 search API 前,必须先按接口名和归一化关键词查缓存。response 或 items,不要再执行 curl。gameList API。缓存文件:d:\skill\tianyi-cloud-game\.cache\api_cache.json
缓存结构:
{
"search:赛车": {
"timestamp": 1714000000000,
"api": "search",
"keyword": "赛车",
"response": {},
"items": []
}
}
缓存键:
gameList:、search:。归一化规则:
我要玩、我想玩、帮我打开、打开、启动、玩、给我来个、给我推荐、推荐、来点、搜搜、搜索、搜、找找、找。吧、呗、啊、呀、一下、看看、类的、之类的、那种、游戏。缓存有效期:
缓存降级:
在任何 curl 前执行:
normalizedKeyword。cacheKey = apiName + ":" + normalizedKeyword。api_cache.json。cacheKey 存在,并且 now - timestamp 未超过有效期,返回缓存结果并跳过 API。api_cache.json。推荐用一个脚本块完成“读缓存/请求 API/写缓存”,不要分散在多次终端调用里,否则容易出现已经查过但仍继续 curl 的问题。
当运行环境是 PowerShell 时,优先使用下面这种结构,把缓存检查和 API 请求放在同一个脚本里。示例中的请求体必须由对象转 JSON,不要手写拼接 JSON。
$ErrorActionPreference = "Stop"
$cacheDir = "d:\skill\tianyi-cloud-game\.cache"
$cacheFile = Join-Path $cacheDir "api_cache.json"
$apiName = "gameList"
$rawKeyword = "我要玩原神"
$ttlMs = 5 * 60 * 1000
function Normalize-Keyword([string]$text) {
$value = $text.Trim()
$value = $value -replace "^(我要玩|我想玩|帮我打开|打开|启动|玩|给我来个|给我推荐|推荐|来点|搜搜|搜索|搜|找找|找)", ""
$value = $value -replace "(吧|呗|啊|呀|一下|看看|类的|之类的|那种|游戏)$", ""
$value = ($value.Trim().ToLower() -replace "\s+", " ")
return $value
}
if (!(Test-Path $cacheDir)) {
New-Item -ItemType Directory -Path $cacheDir | Out-Null
}
$cache = @{}
if (Test-Path $cacheFile) {
try {
$json = Get-Content -Path $cacheFile -Raw -Encoding UTF8
if ($json.Trim()) {
$cache = $json | ConvertFrom-Json -AsHashtable
}
} catch {
$cache = @{}
}
}
$keyword = Normalize-Keyword $rawKeyword
$cacheKey = "$apiName`:$keyword"
$now = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
if ($cache.ContainsKey($cacheKey)) {
$entry = $cache[$cacheKey]
if (($now - [int64]$entry.timestamp) -lt $ttlMs) {
$entry.response | ConvertTo-Json -Depth 20 -Compress
exit 0
}
}
$body = @{ text = $rawKeyword } | ConvertTo-Json -Depth 10 -Compress
$response = Invoke-RestMethod `
-Uri "https://api.play.cn/api/v1/ai/conversation/gameList" `
-Method Post `
-ContentType "application/json" `
-Body $body `
-TimeoutSec 10
$cache[$cacheKey] = @{
timestamp = $now
api = $apiName
keyword = $keyword
response = $response
}
$cache | ConvertTo-Json -Depth 30 | Set-Content -Path $cacheFile -Encoding UTF8
$response | ConvertTo-Json -Depth 20 -Compress
search API 使用同样结构,只需把 $apiName 改为 search,请求体改为:
$body = @{ keyword = $keyword; pageSize = 5 } | ConvertTo-Json -Depth 10 -Compress
请求地址改为:
https://api.play.cn/api/v1/cloud_phone/search
所有请求都要设置 10 秒超时,并对用户输入做 JSON 转义。不要把未转义的用户输入直接拼接到命令字符串里。
API 调用前置条件:
如果这三个条件不满足,禁止请求 API。
用途:具体游戏名精确匹配。
请求地址:https://api.play.cn/api/v1/ai/conversation/gameList
请求方式:POST
请求头:Content-Type: application/json
请求体:
{
"text": "用户原始输入"
}
成功判断:
code 为 200ext 是数组结果路径:
ext[].titleext[].descriptionext[].rateext[].tagsext[].url用途:类型、玩法、题材、相关推荐。
请求地址:https://api.play.cn/api/v1/cloud_phone/search
请求方式:POST
请求头:Content-Type: application/json
请求体:
{
"keyword": "搜索关键词",
"pageSize": 5
}
成功判断:
code 为 0msg 为 successinfo 是数组结果路径:
info[].titleinfo[].introductioninfo[].rateinfo[].tagsinfo[].url把不同接口返回统一成:
{
"title": "游戏名称",
"summary": "一句话简介",
"rate": "4.5",
"tags": [],
"url": "https://h5.play.cn/...",
"source": "gameList 或 search",
"score": 0.92
}
按以下顺序去重:
重复项保留信息更完整、评分更高、来源更精确的一条。
推荐列表排序规则:
gameList 精确结果优先于 search 推荐结果。精确打开排序规则:
从 description 或 introduction 提取一句话:
⭐ 4.8,口碑很不错!⭐ 3.8,还算不错⭐ 暂无评分,先玩玩看?打开前必须清理 URL:
https://h5.play.cn/、https://play.cn/ 及其可信子路径。caf、topRouterId、utm_source、utm_medium、utm_campaign、utm_term、utm_content、spm。type、needLand、gameId、id、channel。打开成功后输出完成提示。若系统打开浏览器失败,展示游戏链接并说明可以手动打开。
错误提示要短、轻松、有下一步建议。
😅 网络有点小情绪,连不上天翼云游戏平台,等会儿再试一次?
如果有 30 分钟内的旧缓存:
😅 平台这会儿有点慢,我先拿最近一次结果给你看看~
⏳ 这会儿网络有点慢,请求卡住了,要不换个关键词再试一次?
第一次无结果时,不要立即失败。根据关键词推断一个相关标签,再调用 search API 搜一次。
推断示例:
原神、开放世界、塞尔达 -> 开放世界CS、枪战、吃鸡 -> 射击王者、MOBA -> 竞技赛车、飞车 -> 赛车三国、仙侠、武侠 -> 角色扮演冒险兜底成功:
🤔 没找到「原关键词」诶,帮你挑了几款「推断标签」类的,看看合不合眼?
兜底仍失败:
🤔 平台里暂时没找到跟「关键词」相关的游戏,换个词试试?比如搜搜「冒险」「射击」「赛车」之类的~
我找到了几个相近的,怕打开错。你选个序号,我再帮你启动~
Invoke-RestMethod 之前,命中时禁止请求接口。pageSize 为 5,不要无意义拉取过多数据。展示推荐列表后保存最近一轮候选:
{
"lastCandidates": [
{
"index": 1,
"title": "游戏名称",
"url": "https://h5.play.cn/...",
"summary": "一句话简介",
"rate": "4.5"
}
],
"lastKeyword": "赛车",
"lastUpdatedAt": 1714000000000
}
候选状态有效期为 10 分钟。超过有效期后,如果用户只说“第几个”,提示重新搜索或让用户补充游戏名。
🔍 正在帮你搜「原神」,稍等一下下~
💡 小贴士:云游戏最大的好处就是不用下载,点开就能玩~
> 🎮 **原神** ⭐ 4.8,口碑很不错!
>
> *开放世界冒险 RPG,自由探索、战斗和养成内容都很丰富。*
>
> 🚀 已经帮你找到啦,马上打开~
✅ 搞定!**原神** 已经在浏览器里等着你了,冲吧!🎮
🔍 正在帮你搜「赛车」,稍等一下下~
💡 小贴士:手机、电脑、电视都能接着玩,换个屏幕也不耽误进度。
🎯 帮你找到了 5 款,来看看有没有对味的~
1. 🥇 **飞速骑行** ⭐ 4.6,口碑很不错!
*主打高速竞速和赛道挑战,适合想快速开跑的玩家。*
2. 🥈 **真实赛车** ⭐ 4.1,还算不错
*偏真实驾驶手感,车辆和赛道选择比较丰富。*
挑中哪个了?跟我说序号或游戏名就行~