best-geo-test 2.0.4-beta.1 → 2.0.4-beta.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.
- package/capabilities/capabilities.json +7 -7
- package/dist/index.cjs +1 -1
- package/guides/answer-card.json +4 -4
- package/guides/article-task.json +1 -1
- package/guides/article.json +1 -1
- package/guides/indexing-query.json +3 -3
- package/guides/knowledge.json +1 -1
- package/guides/material.json +3 -3
- package/guides/publication.json +6 -6
- package/guides/question-task.json +7 -1
- package/guides/question.json +1 -1
- package/guides/scheduled-monitor.json +4 -4
- package/guides/video.json +5 -5
- package/package.json +1 -1
- package/skills/best-geo/SKILL.md +8 -1
|
@@ -777,7 +777,7 @@
|
|
|
777
777
|
"mode": "write",
|
|
778
778
|
"guide": "knowledge",
|
|
779
779
|
"requiresPlan": true,
|
|
780
|
-
"description": "
|
|
780
|
+
"description": "改知识库的名称和标签。加文档用 knowledge.addFiles;改所属项目、删文档要去网页做。",
|
|
781
781
|
"inputSchema": {
|
|
782
782
|
"type": "object",
|
|
783
783
|
"properties": {
|
|
@@ -3217,7 +3217,7 @@
|
|
|
3217
3217
|
"mode": "write",
|
|
3218
3218
|
"guide": "question-task",
|
|
3219
3219
|
"requiresPlan": true,
|
|
3220
|
-
"description": "从 L1
|
|
3220
|
+
"description": "从 L1 结果里挑几个词拓到 L2。不扣费,**每个任务只能做一次**,做过再提交会被拒——所以摘要里列出的挑中词要让用户看清楚再同意。",
|
|
3221
3221
|
"inputSchema": {
|
|
3222
3222
|
"type": "object",
|
|
3223
3223
|
"properties": {
|
|
@@ -3708,7 +3708,7 @@
|
|
|
3708
3708
|
"mode": "read",
|
|
3709
3709
|
"guide": "article-task",
|
|
3710
3710
|
"requiresPlan": false,
|
|
3711
|
-
"description": "
|
|
3711
|
+
"description": "把一个已有文章任务的参数读回来,供「照着上次再来一批」用。**只读参数,不建任务、不扣费**。返回里 warnings 说明哪些资源已失效,missingRequiredFields 列出必须重新指定的字段。拿到后,warnings 和 missingRequiredFields 都为空、用户也没说要改什么,就直接拿这份参数 plan articleTasks.create,摘要里会列出问题、篇数、模型和费用,用户要改就在看摘要时改,改完重新 plan。这两项非空时,先把缺的、失效的跟用户问清楚,不要直接拿去 create。",
|
|
3712
3712
|
"inputSchema": {
|
|
3713
3713
|
"type": "object",
|
|
3714
3714
|
"properties": {
|
|
@@ -4034,7 +4034,7 @@
|
|
|
4034
4034
|
"properties": {
|
|
4035
4035
|
"projectId": { "type": "integer", "minimum": 1, "description": "GEO 项目 id,来自 projects.list" },
|
|
4036
4036
|
"articleId": { "type": "integer", "minimum": 1, "description": "投哪篇" },
|
|
4037
|
-
"mediaId": { "type": "integer", "minimum": 1, "description": "投给哪家。用 mediaPlatforms.list
|
|
4037
|
+
"mediaId": { "type": "integer", "minimum": 1, "description": "投给哪家。用 mediaPlatforms.list 查在架的媒体;价格以 plan 摘要为准" }
|
|
4038
4038
|
},
|
|
4039
4039
|
"required": ["projectId", "articleId", "mediaId"],
|
|
4040
4040
|
"additionalProperties": false
|
|
@@ -4127,7 +4127,7 @@
|
|
|
4127
4127
|
"mode": "write",
|
|
4128
4128
|
"guide": "material",
|
|
4129
4129
|
"requiresPlan": true,
|
|
4130
|
-
"description": "用 AI
|
|
4130
|
+
"description": "用 AI 生成一张图。按张扣费,价格随所选档位不同。不传 model 用第一个启用档;用户点名要哪档时再用 textToImages.models 查 code。费用写在 plan 摘要里。出图是异步的:执行完只拿到任务号,要用 textToImages.get 轮询到 status=3 才有图。",
|
|
4131
4131
|
"inputSchema": {
|
|
4132
4132
|
"type": "object",
|
|
4133
4133
|
"properties": {
|
|
@@ -4349,7 +4349,7 @@
|
|
|
4349
4349
|
"required": ["languageBoost"],
|
|
4350
4350
|
"additionalProperties": false
|
|
4351
4351
|
},
|
|
4352
|
-
"enableClip": { "type": "boolean", "description": "
|
|
4352
|
+
"enableClip": { "type": "boolean", "description": "合成成功后自动发起智能剪辑,是另一笔费用(plan 摘要里分开列)。用户没要剪辑就别开" },
|
|
4353
4353
|
"clipTemplate": { "type": "string", "maxLength": 64, "description": "enableClip 为 true 时必填,用 clipTasks.templates 查" },
|
|
4354
4354
|
"clipEnableAiMedia": { "type": "boolean", "description": "允许剪辑用 AI 生图,按张另外计费。选中 requireAiMedia=true 的模板时必须为 true" },
|
|
4355
4355
|
"clipEnhance": {
|
|
@@ -4830,7 +4830,7 @@
|
|
|
4830
4830
|
"mode": "write",
|
|
4831
4831
|
"guide": "answer-card",
|
|
4832
4832
|
"requiresPlan": true,
|
|
4833
|
-
"description": "
|
|
4833
|
+
"description": "保存答案卡的发布资料(标题/描述/话题标签/封面页)。标题必填;描述、话题标签、封面页不传就保持原样,只改哪项就只传哪项。要清空描述传空字符串、清空话题传 []。不触发重新生成,也不会直接发布,这一步不扣费。",
|
|
4834
4834
|
"inputSchema": {
|
|
4835
4835
|
"type": "object",
|
|
4836
4836
|
"properties": {
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var jt=Object.defineProperty;var Vt=(e,t,n)=>t in e?jt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var se=(e,t,n)=>Vt(e,typeof t!="symbol"?t+"":t,n);var ae="https://nbgeo.aimusiclj.com",Oe="best-geo-test",$e="best-geo-test",Ne="bg-test-cli-",Pe="2.0.4-beta.
|
|
2
|
+
"use strict";var jt=Object.defineProperty;var Vt=(e,t,n)=>t in e?jt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var se=(e,t,n)=>Vt(e,typeof t!="symbol"?t+"":t,n);var ae="https://nbgeo.aimusiclj.com",Oe="best-geo-test",$e="best-geo-test",Ne="bg-test-cli-",Pe="2.0.4-beta.2";var B=2,k=Pe,D=$e,p=Oe,Le="dev",J=Bt(Ft());function Ft(){var e;return(e=process.env.BEST_GEO_API_BASE)!=null?e:ae}var Q=Ne,De=300*1e3,Ue=30*1e3,Me=300*1e3;function Bt(e){return e.replace(/\/+$/,"")}var tt=require("node:child_process");var Ge=require("node:crypto"),X=require("node:os");var d=require("node:fs"),je=require("node:os"),A=require("node:path");var le=require("node:crypto");var _=class extends Error{constructor(n,r,o){super(o);se(this,"reason",n);se(this,"path",r);this.name="LocalConfigError"}},qt={schemaVersion:1,device:null,activeCredential:null,pendingCredential:null};function q(){var e;return(e=process.env.BEST_GEO_CONFIG_DIR)!=null?e:(0,A.join)((0,je.homedir)(),`.${p}`)}function O(){return(0,A.join)(q(),"config.json")}function C(){var n,r,o;let e=O(),t;try{if(!(0,d.existsSync)(e))return null;Gt(e),t=(0,d.readFileSync)(e,"utf8")}catch(i){throw i instanceof _?i:Ve(i,e)}try{let i=JSON.parse(t);if(typeof i!="object"||i==null||i.schemaVersion!==1)throw new Error("unexpected shape");return{schemaVersion:1,device:(n=i.device)!=null?n:null,activeCredential:(r=i.activeCredential)!=null?r:null,pendingCredential:(o=i.pendingCredential)!=null?o:null}}catch{throw new _("corrupted",e,`\u672C\u673A\u914D\u7F6E\u6587\u4EF6\u5185\u5BB9\u4E0D\u5B8C\u6574\u6216\u683C\u5F0F\u4E0D\u5BF9\uFF1A${e}`)}}function Kt(e){let t=q(),n=O(),r=(0,A.join)(t,`.config.json.${(0,le.randomBytes)(6).toString("hex")}.tmp`);try{(0,d.existsSync)(t)||(0,d.mkdirSync)(t,{recursive:!0,mode:448});let o=(0,d.openSync)(r,"wx",384);try{(0,d.writeSync)(o,`${JSON.stringify(e,null,2)}
|
|
3
3
|
`),(0,d.fsyncSync)(o)}finally{(0,d.closeSync)(o)}(0,d.renameSync)(r,n)}catch(o){if((0,d.existsSync)(r))try{(0,d.unlinkSync)(r)}catch{}throw Ve(o,n)}}function T(e){var n;let t=e((n=C())!=null?n:{...qt});return Kt(t),t}function Gt(e){var r;if(process.platform==="win32")return;let t=(0,d.statSync)(e),n=(r=process.getuid)==null?void 0:r.call(process);if(n!=null&&t.uid!==n)throw new _("not_owner",e,`\u672C\u673A\u914D\u7F6E\u6587\u4EF6\u4E0D\u5C5E\u4E8E\u5F53\u524D\u7528\u6237\uFF1A${e}`);if((t.mode&63)!==0)throw new _("permissions_too_open",e,`\u672C\u673A\u914D\u7F6E\u6587\u4EF6\u6743\u9650\u8FC7\u5BBD\uFF08\u540C\u673A\u5176\u4ED6\u7528\u6237\u53EF\u8BFB\uFF09\uFF1A${e}`)}function Ve(e,t){let n=e==null?void 0:e.code;return n==="EACCES"||n==="EPERM"||n==="EROFS"?new _("denied",t,`\u6CA1\u6709\u6743\u9650\u8BFB\u5199\u672C\u673A\u914D\u7F6E\uFF1A${t}`):e instanceof Error?e:new Error(String(e))}var Fe=3600*1e3;function Be(){return(0,A.join)(q(),"pending-uploads")}var Ht=/^plan_[0-9a-zA-Z]+$/;function de(e){return Ht.test(e)?(0,A.join)(Be(),`${e}.json`):null}function W(e){var n;let t=de(e);if(t==null||!(0,d.existsSync)(t))return null;try{let r=JSON.parse((0,d.readFileSync)(t,"utf8"));return Date.now()-((n=r==null?void 0:r.createdAt)!=null?n:0)<Fe?r:null}catch{return null}}function qe(e,t){let n=de(e);if(n==null)throw new Error(`\u4E0D\u5408\u6CD5\u7684\u8BA1\u5212 ID:${e}`);let r=Be();(0,d.mkdirSync)(r,{recursive:!0,mode:448}),zt(r);let o=(0,A.join)(r,`.${e}.${(0,le.randomBytes)(6).toString("hex")}.tmp`);try{(0,d.writeFileSync)(o,JSON.stringify(t),{mode:384}),(0,d.renameSync)(o,n)}catch(i){if((0,d.existsSync)(o))try{(0,d.unlinkSync)(o)}catch{}throw i}}function Ke(e){let t=de(e);if(t!=null)try{(0,d.unlinkSync)(t)}catch{}}function zt(e){let t=(0,A.join)(q(),"pending-uploads.json");try{(0,d.existsSync)(t)&&(0,d.unlinkSync)(t)}catch{}let n;try{n=(0,d.readdirSync)(e)}catch{return}for(let r of n){if(r.endsWith(".tmp")){try{let i=(0,A.join)(e,r);Date.now()-(0,d.statSync)(i).mtimeMs>=Fe&&(0,d.unlinkSync)(i)}catch{}continue}if(!r.endsWith(".json"))continue;let o=r.slice(0,-5);if(W(o)==null)try{(0,d.unlinkSync)((0,A.join)(e,r))}catch{}}}function He(){var t,n;let e=(t=C())==null?void 0:t.device;return(n=e==null?void 0:e.deviceId)!=null&&n.startsWith(Q)?e.deviceId:null}function Y(){var r,o;let e={deviceName:(0,X.hostname)().slice(0,50),platform:`${(0,X.platform)()}-${process.arch}`},t=(r=C())==null?void 0:r.device;if((o=t==null?void 0:t.deviceId)!=null&&o.startsWith(Q))return t.deviceName===e.deviceName&&t.platform===e.platform?t:T(i=>({...i,device:{...t,...e}})).device;let n={deviceId:`${Q}${(0,Ge.randomUUID)()}`,...e};return T(i=>({...i,device:n})).device}function ze(){return`cli_${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`}function E(e,t=ze()){return{ok:!0,code:"OK",requestId:t,data:e}}function l(e,t,n={}){var r;return{ok:!1,code:e,message:t,requestId:(r=n.requestId)!=null?r:ze(),...n.data==null?{}:{data:n.data},...n.nextAction==null?{}:{nextAction:n.nextAction}}}function a(e){process.stdout.write(`${JSON.stringify(e)}
|
|
4
4
|
`),e.ok||(process.exitCode=1)}async function x(e,t={}){var i,s;let n=new URL(`${J}/v1/agent-cli${e}`);for(let[c,f]of Object.entries((i=t.query)!=null?i:{}))if(f!=null)for(let m of Array.isArray(f)?f:[f])n.searchParams.append(c,String(m));let r={"X-GEO-CLI-Version":k,"X-GEO-Protocol-Version":String(B),"X-GEO-CLI-Package":D};t.projectId!=null&&(r["X-Geo-Product-Id"]=String(t.projectId));let o=null;try{o=He()}catch{}o&&(r["X-Device-ID"]=o),t.apiKey&&(r.Authorization=`Bearer ${t.apiKey}`),t.body!=null&&(r["Content-Type"]="application/json");try{let c=await fetch(n,{method:(s=t.method)!=null?s:"GET",headers:r,body:t.body==null?void 0:JSON.stringify(t.body),signal:AbortSignal.timeout(t.isWrite?Me:Ue)}),f=await c.text();try{let m=JSON.parse(f);return Jt(m)?m:l("SERVER_ERROR",`\u670D\u52A1\u7AEF\u8FD4\u56DE\u4E86\u975E\u9884\u671F\u5185\u5BB9\uFF08HTTP ${c.status}\uFF09`,{data:{transportFailure:!0}})}catch{return l("SERVER_ERROR",`\u670D\u52A1\u7AEF\u8FD4\u56DE\u4E86\u975E\u9884\u671F\u5185\u5BB9\uFF08HTTP ${c.status}\uFF09`,{data:{transportFailure:!0}})}}catch(c){return c instanceof Error&&(c.name==="TimeoutError"||c.name==="AbortError")?l("SERVER_ERROR",t.isWrite?"\u670D\u52A1\u7AEF\u5904\u7406\u8D85\u65F6,\u8FD9\u6B21\u5199\u5165\u7ED3\u679C\u672A\u77E5":"\u670D\u52A1\u7AEF\u54CD\u5E94\u8D85\u65F6",{data:{transportFailure:!0},nextAction:t.isWrite?{type:"ask_user",message:"\u8D85\u65F6\u4E0D\u4EE3\u8868\u6CA1\u5199\u8FDB\u53BB \u2014\u2014 \u670D\u52A1\u7AEF\u53EF\u80FD\u8FD8\u5728\u5904\u7406\u3002**\u5148\u7528\u5BF9\u5E94\u7684\u67E5\u8BE2\u80FD\u529B\u786E\u8BA4\u4E00\u904D**,\u786E\u5B9E\u6CA1\u6709\u518D\u91CD\u65B0 plan;\u76F4\u63A5\u91CD\u8BD5\u4F1A\u5EFA\u51FA\u91CD\u590D\u7684\u4E00\u4EFD,\u800C\u4E14\u4F1A\u518D\u6263\u4E00\u6B21\u8D39\u3002"}:{type:"ask_user",message:"\u670D\u52A1\u7AEF\u54CD\u5E94\u592A\u6162\u3002\u7A0D\u540E\u91CD\u8BD5\u540C\u4E00\u6761\u547D\u4EE4\u5373\u53EF,\u67E5\u8BE2\u4E0D\u4F1A\u4EA7\u751F\u4EFB\u4F55\u5199\u5165"}}):l("SERVER_ERROR",`\u65E0\u6CD5\u8FDE\u63A5\u670D\u52A1\u7AEF\uFF1A${c instanceof Error?c.message:String(c)}`,{data:{transportFailure:!0},nextAction:{type:"ask_user",message:"\u8BF7\u786E\u8BA4\u7F51\u7EDC\u53EF\u7528\uFF0C\u4EE5\u53CA\u670D\u52A1\u7AEF\u5730\u5740\u914D\u7F6E\u6B63\u786E"}})}}function Jt(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.ok=="boolean"&&typeof t.code=="string"}function Qt(e){var t;return!e.ok&&((t=e.data)==null?void 0:t.transportFailure)===!0}function ce(e){return e.ok||Qt(e)?!1:["AUTH_EXPIRED","DEVICE_MISMATCH","ACCESS_DENIED","AUTH_REQUIRED","VALIDATION_FAILED"].includes(e.code)}function U(){var e,t,n;return(n=(t=(e=C())==null?void 0:e.activeCredential)==null?void 0:t.apiKey)!=null?n:null}function Z(){var e,t;return(t=(e=C())==null?void 0:e.activeCredential)!=null?t:null}function Je(){var e,t;return(t=(e=C())==null?void 0:e.pendingCredential)!=null?t:null}function Qe(e){T(t=>({...t,pendingCredential:{apiKey:e,startedAt:new Date().toISOString()}}))}function pe(){T(e=>({...e,pendingCredential:null}))}function ue(e){return T(t=>{let n=t.pendingCredential;return n?{...t,activeCredential:{apiKey:n.apiKey,...e},pendingCredential:null}:t}).activeCredential}function We(){T(e=>({...e,activeCredential:null,pendingCredential:null}))}var R=require("node:crypto"),Ze=require("node:http");function Xe(e){let t=`
|
|
5
5
|
(function () {
|
package/guides/answer-card.json
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"step": 6,
|
|
41
41
|
"action": "轮询批次到终态",
|
|
42
42
|
"capability": "answerCards.batch",
|
|
43
|
-
"note": "status=6 全部完成、7 部分失败、8 全部失败。看 items 里每一项的 status 和 imageUrls,status=4 是失败页。⚠️ 现在没有重跑单页的能力,有失败页时告知用户失败的页数(失败页的出图费会自动退回),引导他去网页处理,不要自己编一个操作去重试。"
|
|
43
|
+
"note": "注意这里是**批次**状态;答案卡**任务**本身的终态是 8 已完成 / 9 部分失败 / 10 失败,两套数字不通用,念给用户一律用 statusLabel。status=6 全部完成、7 部分失败、8 全部失败。看 items 里每一项的 status 和 imageUrls,status=4 是失败页。⚠️ 现在没有重跑单页的能力,有失败页时告知用户失败的页数(失败页的出图费会自动退回),引导他去网页处理,不要自己编一个操作去重试。"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"step": 7,
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"step": 8,
|
|
53
53
|
"action": "(另一条路)导入现成图片",
|
|
54
54
|
"capability": "answerCards.import",
|
|
55
|
-
"note": "用户已经有做好的图时走这条,不经过分析和出图。先确认每张图都在素材库里:本地文件用 images.create 逐张上传拿 imageId
|
|
55
|
+
"note": "用户已经有做好的图时走这条,不经过分析和出图。先确认每张图都在素材库里:本地文件用 images.create 逐张上传拿 imageId,传完就能导入,不用等图片处理完。上传时 tags 默认填两个:「答案卡」和这张卡的发布标题(就是之后 answerCards.import 要传的 publishTitle),方便以后在素材库里按卡找回这些图;用户另外指定了标签就一并加上。整条路有两类收费:每张图 images.create 一次上传费,answerCards.import 一次答案卡基础费。plan 本身不扣费,用户说了要导入就直接去 plan,不要在 plan 之前先停下来谈费用或自己去查价格——具体金额就在 plan 返回的 notice 里,随摘要一起告诉用户、用户同意就 apply。多张图时把每张 images.create 都先 plan 好,摘要和费用合在一条消息里让用户一次确认,再逐个 apply,不要一张一张问。第一条确认消息里顺带说一句「传完还要再确认一次导入,那一步另收一笔答案卡基础费」;上传全部 apply 成功后,马上 plan answerCards.import,把摘要发给用户确认,不要再问「要不要继续导入」。导入后直接是已完成,可以 savePublishInfo 改发布资料,再用 publicationTasks.createImage 发布。"
|
|
56
56
|
}
|
|
57
57
|
],
|
|
58
58
|
"askUserWhen": [
|
|
59
59
|
"用户没说清内容来源:给的是文章还是要自己写一段正文,两者只能选一个",
|
|
60
60
|
"用户没说清视觉方式:不确定就用「AI 智能匹配」(visualMode=1),别替用户随便指定一个模板或编一段风格描述",
|
|
61
|
-
"脚本已就绪(status=2
|
|
61
|
+
"脚本已就绪(status=2):把拆好的页面简要说给用户听,同时 plan 好 answerCards.generate,把费用摘要放进同一条消息——「不改就回复同意出图;要改告诉我改哪」。用户要改,就先 savePages(之前那份 generate 计划直接丢掉),改完重新 get、重新 plan generate",
|
|
62
62
|
"确认生成或导入之前:answerCards.generate(出图费 + 基础费两笔)和 answerCards.import(一笔基础费)都收费,必须把 plan 返回的 notice 里的费用说明念清楚,等用户明确同意再 apply",
|
|
63
63
|
"有失败页时:告知用户失败的页数和退款情况,问他要不要去网页处理,不要替他决定"
|
|
64
64
|
],
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"PLAN_STALE": "确认期间这条任务(脚本或发布资料)被别人改过。重新 answerCards.get 读当前内容、重新 plan,把新摘要再给用户确认一次,不要拿旧 planId 重试。导入时报这个码,是确认期间有图片被停用/删除/处理失败:重新生成计划,给用户确认后再执行。",
|
|
83
83
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次——旧 planId 已经不能用了。",
|
|
84
84
|
"PLAN_COST_CHANGED": "generate 在 apply 时发现要出的页数和确认时不一样(多半是确认期间脚本被改过),或者单价变了;import 报这个码是基础费价格变了。重新 plan,把新的页数和费用说明再念给用户确认一次,不要直接重试 apply。",
|
|
85
|
-
"QUOTA_EXCEEDED": "
|
|
85
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
86
86
|
"SERVER_ERROR": "服务端故障,稍后重试;反复出现请把 message 告知用户,不要自己判断原因。"
|
|
87
87
|
},
|
|
88
88
|
"completionCriteria": "查询类:已如实呈现任务/批次的真实状态,没跑完就说清它还在哪个阶段。写入类:answerCards.create/savePages/savePublishInfo 是不扣费的资料动作,用户看过 plan 摘要并同意后 apply 即可;answerCards.generate 必须让用户看清两笔费用并明确同意才能 apply,apply 成功后要告诉用户去哪查进度(answerCards.batch);answerCards.import 同样要让用户看清那笔基础费并明确同意后才能 apply,apply 成功后答案卡直接是已完成。",
|
package/guides/article-task.json
CHANGED
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"VALIDATION_FAILED": "参数不合法,按 capabilities 里的 inputSchema 修正后重试。提示词/模型不存在、提示词类型不对、项目下没有知识资料、图片数量不够配图,都走这个码,message 里写明了是哪一种。",
|
|
71
71
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次——旧 planId 已经不能用了。",
|
|
72
72
|
"PLAN_COST_CHANGED": "扣费方式在确认期间变了。重新 plan,把新的费用说明再念给用户。",
|
|
73
|
-
"QUOTA_EXCEEDED": "
|
|
73
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
74
74
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。常见原因是站点侧配置缺失或服务端临时故障。**apply 阶段先别重试**——可能已经建出来了,先用 articleTasks.list 确认;把 message 和 requestId 一起转达给用户,让他联系服务商。"
|
|
75
75
|
},
|
|
76
76
|
"completionCriteria": "读:已经如实说明任务跑到哪一步、写出来多少篇、审核通过多少。写:plan 摘要已原样念给用户、用户明确同意、apply 成功,并告诉了他任务在后台跑、大概要等一会儿。"
|
package/guides/article.json
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"PLAN_STALE": "这篇文章在用户确认期间被别人改过。重新 articles.get 读当前内容、重新 plan,把新摘要再给用户确认一次。不要拿旧 planId 重试。",
|
|
83
83
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次——旧 planId 已经不能用了。",
|
|
84
84
|
"PLAN_COST_CHANGED": "扣费方式在确认期间变了。重新 plan,把新的费用说明再念给用户。",
|
|
85
|
-
"QUOTA_EXCEEDED": "
|
|
85
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
86
86
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。常见原因是站点侧配置缺失或服务端临时故障。**apply 阶段先别重试**——可能已经写进去了,先用 articles.list 确认;把 message 和 requestId 一起转达给用户,让他联系服务商。"
|
|
87
87
|
},
|
|
88
88
|
"completionCriteria": "读:已经如实呈现用户关心的文章列表(含总数)或指定那一篇的信息,用户要正文时才给了正文。写:plan 摘要已原样念给用户、用户明确同意、apply 成功,并把结果(文章 ID、还差不差封面)告诉了他。"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{
|
|
18
18
|
"step": 2,
|
|
19
19
|
"action": "跟用户对齐问哪些问题、问哪几家",
|
|
20
|
-
"note": "问题和平台是多对多:questions(1~100 个)× platforms,每个组合问一次。提问次数 = 问题数 ×
|
|
20
|
+
"note": "问题和平台是多对多:questions(1~100 个)× platforms,每个组合问一次。提问次数 = 问题数 × 平台数,费用按这个算,plan 摘要里会写清楚,随摘要一起告诉用户。常见的是一个平台问多个问题,也可以多个平台对比同一批问题。"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"step": 3,
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"askUserWhen": [
|
|
47
47
|
"要问哪些问题没定下来——问偏了,这次的提问次数全花在用户不关心的问题上",
|
|
48
48
|
"要问哪几家 AI 没说清;别自己挑一批平台就提交",
|
|
49
|
-
"问题数 ×
|
|
49
|
+
"问题数 × 平台数很多(比如上百次)时,plan 摘要里的次数和费用要念得特别清楚;用户说了要问就直接 plan,不要在 plan 之前另外确认一次",
|
|
50
50
|
"用户要对话截图或分享链接时才开 withShareUrl,开了这些平台按两份计费"
|
|
51
51
|
],
|
|
52
52
|
"forbidden": [
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"errorRecovery": {
|
|
67
67
|
"ACCESS_DENIED": "taskId 不在当前 GEO 项目里,确认 projectId 和建任务时是同一个;要换项目先问用户。",
|
|
68
68
|
"VALIDATION_FAILED": "参数不合法,message 里写明了是哪一种:平台当前不可用、云端跑不了某个平台、指定的厂商跑不了某个平台、问题超过 100 个、或 taskId 不是 AI 查询任务(周期执行或插件采集的计划)。按 message 改,改完重新 plan。",
|
|
69
|
-
"QUOTA_EXCEEDED": "
|
|
69
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够,也可能是这个 GEO 项目的搜索问题库满了(新问题会加进问题库)。任务都没有建出来。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
70
70
|
"PLAN_COST_CHANGED": "扣费方式在确认期间变了。重新 plan,把新的费用说明再念给用户。",
|
|
71
71
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次,旧 planId 已经不能用了。"
|
|
72
72
|
}
|
package/guides/knowledge.json
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"VALIDATION_FAILED": "参数不合法。常见原因:files 为空、某个文档缺 name 或 file、知识库名称为空或只有空格。按提示补齐后重试。**还有一种与参数无关的情况**:站点还没配置这个功能的价格——这时按 nextAction 说的让用户联系服务商,别去改参数重试,改了也过不去。分辨方法是看 nextAction.message。",
|
|
65
65
|
"PLAN_STALE": "确认期间这个知识库被别人改过。重新 plan,把新摘要再给用户确认一次。",
|
|
66
66
|
"PLAN_COST_CHANGED": "确认之后扣费方式变了(比如管理员把这个功能改成从另一种账户扣)。用户上次点头同意的不是现在这笔,**别直接重试 apply**。重新 plan,把新的费用说明再给用户确认一次。注意:响应里**不含**「原来是什么、现在是什么」,别向用户复述具体是从哪种变成了哪种。",
|
|
67
|
-
"QUOTA_EXCEEDED": "
|
|
67
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
68
68
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。常见原因是站点侧配置缺失或服务端临时故障。**apply 阶段先别重试**——可能已经写进去了,先用 knowledge.get / knowledge.list 确认;把 message 和 requestId 一起转达给用户,让他联系服务商。"
|
|
69
69
|
},
|
|
70
70
|
"completionCriteria": "查询类:已如实呈现知识库列表或指定那个的文档解析状态。新建类:用户看过摘要并明确同意后才执行,且执行后说清了「正在解析、暂不可用」。",
|
package/guides/material.json
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"step": 5,
|
|
35
35
|
"action": "上传图片走 images.create,给本机路径",
|
|
36
36
|
"capability": "images.create",
|
|
37
|
-
"note": "png/jpg/jpeg,最大 2MB。超了会在本机就报错,报错里写着当前多大、上限多少——把这个如实告诉用户,并问他要不要你先压一下(macOS 自带 sips,多数机器有 ffmpeg),压完拿新文件重新 plan
|
|
37
|
+
"note": "png/jpg/jpeg,最大 2MB。超了会在本机就报错,报错里写着当前多大、上限多少——把这个如实告诉用户,并问他要不要你先压一下(macOS 自带 sips,多数机器有 ffmpeg),压完拿新文件重新 plan。按张扣一次费用。多张图就逐张 plan,摘要和费用合在一条消息里让用户一次确认,再逐个 apply。"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"step": 6,
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"step": 8,
|
|
52
52
|
"action": "用户要的图不是本机文件、而是想让 AI 画一张时,走文生图",
|
|
53
53
|
"capability": "textToImages.create",
|
|
54
|
-
"note": "
|
|
54
|
+
"note": "用户点名了档位就用那一档(code 从 textToImages.models 查,别猜);没点名就不传 model,直接 plan,摘要里会写清用的是哪一档、扣多少,随摘要告诉用户,他想换档再重新 plan。apply 只拿到任务号,出图是异步的,要用 textToImages.get 轮询到 status=3(成功)才有图。想知道当前 GEO 项目还有几张没出,用 textToImages.countUncompleted。按张扣费,价格随档位不同。"
|
|
55
55
|
}
|
|
56
56
|
],
|
|
57
57
|
"askUserWhen": [
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次——旧 planId 已经不能用了,文件也要重新走一遍上传。",
|
|
79
79
|
"UPLOAD_FAILED": "文件传到一半断了。素材记录还没建,什么都没留下——把情况告诉用户,重新走一遍 plan 就行,不要反复重试 apply。",
|
|
80
80
|
"PLAN_COST_CHANGED": "扣费方式在确认期间变了。重新 plan,把新的费用说明再念给用户。",
|
|
81
|
-
"QUOTA_EXCEEDED": "
|
|
81
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
82
82
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。常见原因是站点侧配置缺失或服务端临时故障。**apply 阶段先别重试**——可能已经建出来了,先用 images.list / videos.list 确认;把 message 和 requestId 一起转达给用户,让他联系服务商。"
|
|
83
83
|
},
|
|
84
84
|
"completionCriteria": "查询类:已如实呈现用户关心的素材列表或指定那一条的信息。写入类(新建/改名/改标签):用户看过 plan 摘要并明确同意后才执行,执行完把结果告诉了他。",
|
package/guides/publication.json
CHANGED
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"step": 8,
|
|
53
53
|
"action": "要停下来用 publicationTasks.pause,改主意了用 delete",
|
|
54
54
|
"capability": "publicationTasks.pause",
|
|
55
|
-
"note": "两个都只对**还没发出去**的记录有效(删除会连暂停中的一起删掉)。已经发成功的稿子留在平台上,CLI
|
|
55
|
+
"note": "两个都只对**还没发出去**的记录有效(删除会连暂停中的一起删掉)。已经发成功的稿子留在平台上,CLI 撤不回来——用户要撤那些,只能去各平台自己删,这一点必须说明白,别让他以为暂停就等于撤回。另外,费用是在建任务时按记录条数结算的;删除只是让还没发出去的记录不再发,不会改动已经结算的那笔,用户点删除前得知道这一点。**例外是外部导入的任务**(typeLabel=外部导入):它不能暂停或恢复;删除时会连同名下已发布的记录一起删掉,收录统计也会跟着减少,计划摘要会单独写出来,一定要念给用户。"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"step": 9,
|
|
59
|
-
"action": "媒体投稿:先 mediaPlatforms.list
|
|
59
|
+
"action": "媒体投稿:先 mediaPlatforms.list 看有哪些媒体;用户要投就直接 plan,价格以 plan 摘要为准",
|
|
60
60
|
"capability": "mediaPlatforms.get",
|
|
61
|
-
"note": "
|
|
61
|
+
"note": "列表里的价格是分页快照,只能用来帮用户挑媒体,不要拿它当报价。用户只是问「某家现在多少钱」、还没决定投时,用 mediaPlatforms.get 查实时价;决定投了就直接 plan——摘要里逐家列的就是实时价,也是最终扣费的依据。"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"step": 10,
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"不要在用户确认之前 apply 任何发布或投稿的计划——执行之后稿子就真的出去了",
|
|
91
91
|
"不要只报总数或总价就让用户确认。发布要念「哪篇发到哪个号」,投稿要念「哪家多少钱」",
|
|
92
92
|
"不要拿投稿记录回答自媒体发布的问题,反过来也一样——两条链路的状态含义不同",
|
|
93
|
-
"
|
|
93
|
+
"不要用列表里的媒体价格当报价。要投就以 plan 摘要里逐家列的价格为准;只是询价时才用 mediaPlatforms.get",
|
|
94
94
|
"不要给自媒体发布的失败编造原因,也不要去读 errorMessage——那个字段不存在",
|
|
95
95
|
"不要把 refund_pending 说成「已退款」——那笔钱现在还在用户账外,说错了他就不会再追",
|
|
96
96
|
"不要拿 currentPrice 当这笔的花费念——那是媒体现在的挂牌价,实际扣了多少看 chargedAmount",
|
|
@@ -118,14 +118,14 @@
|
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
"code": "QUOTA_EXCEEDED",
|
|
121
|
-
"action": "
|
|
121
|
+
"action": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。"
|
|
122
122
|
}
|
|
123
123
|
],
|
|
124
124
|
"completionCriteria": [
|
|
125
125
|
"回答「发了没有」时给出了状态名称、以及成功的链接或失败的说明",
|
|
126
126
|
"批量投稿执行完,报的是结果里的 netChargedTotal(单位元),不是自己按成功家数乘单价算出来的",
|
|
127
127
|
"有 refund_pending 的项时,说清楚「这笔钱还没退回来,系统会自动补退」,不能说成已退款",
|
|
128
|
-
"
|
|
128
|
+
"涉及花钱的投稿,用户确认的是 plan 摘要里逐家列出的价格和合计,且逐家念过明细",
|
|
129
129
|
"建任务或投稿前,把「哪篇发到哪儿、花多少钱、发出去撤不回来」都跟用户讲清楚了,他明确点头才 apply"
|
|
130
130
|
]
|
|
131
131
|
}
|
|
@@ -45,6 +45,12 @@
|
|
|
45
45
|
"action": "任务失败时才用 questionTasks.retry",
|
|
46
46
|
"capability": "questionTasks.retry",
|
|
47
47
|
"note": "按原参数重跑,费用按这次的条数重新算一笔。只有状态是失败(3)的任务能重试。"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"step": 8,
|
|
51
|
+
"action": "(另一条路)用户要的是关键词树而不是一批问题时,走 keywordTasks",
|
|
52
|
+
"capability": "keywordTasks.create",
|
|
53
|
+
"note": "和 questionTasks 不是一回事:questionTasks 一次性生成一批搜索问题,可以导进问题库;keywordTasks 是分阶段的关键词树——先从一个词拓出一批 L1 词,用户挑几个,再拓 L2。顺序是 keywordTasks.create(按任务扣一次费,异步跑)→ 过一会儿 keywordTasks.get 看 L1 结果 →(用户对 L1 不满意时 keywordTasks.updateL1 整批换掉,不扣费)→ keywordTasks.expandL2 从 result[0].output 里挑词拓到 L2(不扣费,每个任务只能做一次,做过再提交会被拒,所以摘要里挑中的词要让用户看清楚再同意)。"
|
|
48
54
|
}
|
|
49
55
|
],
|
|
50
56
|
"askUserWhen": [
|
|
@@ -67,7 +73,7 @@
|
|
|
67
73
|
"PLAN_STALE": "任务在用户确认期间被动过(多半是别人也导了一批)。重新 questionTasks.get 读当前状态、重新 plan,把新摘要再给用户确认一次。",
|
|
68
74
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次——旧 planId 已经不能用了。",
|
|
69
75
|
"PLAN_COST_CHANGED": "扣费方式在确认期间变了。重新 plan,把新的费用说明再念给用户。",
|
|
70
|
-
"QUOTA_EXCEEDED": "
|
|
76
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
71
77
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。常见原因是站点侧配置缺失或服务端临时故障。**apply 阶段先别重试**——可能已经建出来了,先用 questionTasks.list 确认;把 message 和 requestId 一起转达给用户,让他联系服务商。"
|
|
72
78
|
},
|
|
73
79
|
"completionCriteria": "读:已经如实说明任务跑到哪一步、生成了哪些问题。写:plan 摘要已原样念给用户、用户明确同意、apply 成功,并告诉了他任务在后台跑(新建/重试)或者哪些问题已经进了问题库(导入)。"
|
package/guides/question.json
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"errorRecovery": {
|
|
53
53
|
"ACCESS_DENIED": "这条数据不在当前 GEO 项目里,用当前项目的列表能力重新查;要换项目先问用户。",
|
|
54
54
|
"VALIDATION_FAILED": "参数不合法,按 capabilities 里的 inputSchema 修正后重试。",
|
|
55
|
-
"QUOTA_EXCEEDED": "
|
|
55
|
+
"QUOTA_EXCEEDED": "多半是该 GEO 项目的搜索问题会超过 800 条上限,也可能是套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。"
|
|
56
56
|
},
|
|
57
57
|
"completionCriteria": "已经把用户关心的问题列表(或指定的那一条)如实呈现,并说明了总数。",
|
|
58
58
|
"writeFlow": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
{
|
|
23
23
|
"step": 3,
|
|
24
24
|
"action": "跟用户对齐要问哪些问题、多久问一次",
|
|
25
|
-
"note": "问题条数 × 平台数 =
|
|
25
|
+
"note": "问题条数 × 平台数 = 每跑一次的提问次数,费用按它算,plan 摘要的 notice 里有具体数字,随摘要告诉用户。频率有四种:每天、每周固定几天、每隔几天、只跑一次。「几点跑」可以精确给 hours,也可以只说一天跑几次让系统均分。"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"step": 4,
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"要问哪些问题没定下来。这是计划的输入,问偏了以后每一次执行都在问偏的问题上花工夫",
|
|
67
67
|
"平台和采集方式没定。云端和插件支持的平台不一样,也直接决定扣不扣算力",
|
|
68
68
|
"多久跑一次没说清;别自己定一个频率就提交",
|
|
69
|
-
"
|
|
69
|
+
"用户只是问「上次跑了没」「能不能快点出结果」,并没有说要立刻跑时,先问他要不要立即执行一次——立即执行会马上发下去、按次扣费。用户已经明确说要立刻跑,就直接 plan runNow,费用随摘要说"
|
|
70
70
|
],
|
|
71
71
|
"forbidden": [
|
|
72
72
|
"不要凭印象填 platforms。可用平台按代理配置走,每个代理不一样,必须以 indexingPlatforms.list 的返回为准",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"不要拿 metrics 的数字去回答「AI 具体怎么说的」。那是 answers 的活,metrics 里没有一个字是 AI 说的原话"
|
|
81
81
|
],
|
|
82
82
|
"completionCriteria": [
|
|
83
|
-
"
|
|
83
|
+
"新建/修改类:用户看过 plan 摘要(计划名、每轮提问次数、频率、费用)并同意后 apply 成功,并把结果告诉了用户",
|
|
84
84
|
"runNow:apply 成功即算发出去了,不等于跑完——别拿它当结果汇报",
|
|
85
85
|
"看进度类:runs 里 taskFinished 追平 taskTotal、status=1 才算这一轮跑完",
|
|
86
86
|
"看效果类:metrics 取到了数并说清了它对应哪个时间范围、哪个平台"
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"PLAN_COST_CHANGED": "扣费方式在确认期间变了。重新 plan,把新的费用说明再念给用户。",
|
|
92
92
|
"PLAN_STALE": "计划在用户确认期间被改过。重新 get 读当前配置、重新 plan,把新摘要再给用户确认一次——runNow 也一样,因为摘要里承诺的提问次数可能已经变了。",
|
|
93
93
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次,旧 planId 已经不能用了。",
|
|
94
|
-
"QUOTA_EXCEEDED": "
|
|
94
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
95
95
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。runNow 时最常见的原因是**这个计划已经有一次执行在跑**——用 runs 看最近一次的状态,跑完了再重新 plan runNow,别连着重试。其他情况多半是站点侧配置缺失或服务端临时故障,把 message 和 requestId 一起转达给用户。"
|
|
96
96
|
}
|
|
97
97
|
}
|
package/guides/video.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"step": 4,
|
|
28
28
|
"action": "如果用户还要剪辑成片,在提交时一并打开",
|
|
29
29
|
"capability": "clipTasks.templates",
|
|
30
|
-
"note": "把 enableClip 设成 true 并给 clipTemplate(模板 code 从 clipTasks.templates
|
|
30
|
+
"note": "把 enableClip 设成 true 并给 clipTemplate(模板 code 从 clipTasks.templates 查)。这样数字人成片后会自动发起剪辑,不用再提交一次。剪辑是另一笔费用,plan 摘要里会和数字人分开列出,随摘要念给用户。用户已经明确说了要剪辑就直接打开、明确说不要就不开,都不用再问;没说的话,和其它 plan 前还缺的信息在同一条消息里一起问(见 askUserWhen)。"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"step": 5,
|
|
@@ -50,14 +50,14 @@
|
|
|
50
50
|
],
|
|
51
51
|
"askUserWhen": [
|
|
52
52
|
"用户没说画质:LITE 和 PRO 差价明显,让他自己选,别默认",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
53
|
+
"用户没说要不要剪辑:要问,但和形象、音色、画质等 plan 前还缺的信息放在同一条消息里一起问,不要单独问一轮;问的时候顺带说剪辑是另一笔费用,具体金额在 plan 摘要里。用户已经明确说了要或不要剪辑,就不要再问,直接按他说的开或不开",
|
|
54
|
+
"所选剪辑模板 requireAiMedia 是 true:问剪辑时一并说明这个模板需要 AI 生图、按张另计;用户已同意剪辑且模板要求时直接打开(dhVideos.create 里是 clipEnableAiMedia,clipTasks.create 里是 enableAiMedia),费用随 plan 摘要说,不用再单独问",
|
|
55
55
|
"用户只说了「做个视频」但没给文案,也没给音频地址:这两样必须有一样,问清楚要哪种",
|
|
56
56
|
"私有形象/音色查出来是空的:告诉用户可以用平台公共资源,让他从公共库里挑一个,不要自己随便选一个就提交"
|
|
57
57
|
],
|
|
58
58
|
"forbidden": [
|
|
59
59
|
"不要同时传 text 和 audioUrl。两种输入模式只能选一种,都传会被直接拒绝",
|
|
60
|
-
"
|
|
60
|
+
"用户没要剪辑时不要自作主张打开 enableClip / clipEnableAiMedia;费用都会写在 plan 摘要里,必须随摘要念给用户",
|
|
61
61
|
"不要把 plan 里的预估金额说成最终价格。这条链路提交时不扣费,成片之后按真实时长结算,实际可能多也可能少——照实说",
|
|
62
62
|
"不要只填 personName 或只填 personIntro。人物名片必须成对,只给一半的话模板会拿预置的示例内容把另一半填上,成片上就出现一个不存在的人",
|
|
63
63
|
"不要自己编 trainingId / voiceId / template。这三个都要从对应的查询接口里取,猜的值提交后会被上游拒",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"PLAN_STALE": "确认期间来源数字人任务合成完了、回填了真实时长,那份按兜底秒数算出来的报价已经不作数。重新 plan,把新的金额再念给用户确认一次——底板只是进度在动不会触发这个码,所以不用担心一直撞。",
|
|
74
74
|
"PLAN_EXPIRED": "计划超过 30 分钟没执行。重新 plan,把新摘要再给用户确认一次。",
|
|
75
75
|
"PLAN_COST_CHANGED": "单价在确认期间被改过。重新 plan,把新的费用说明再念给用户。",
|
|
76
|
-
"QUOTA_EXCEEDED": "
|
|
76
|
+
"QUOTA_EXCEEDED": "余额不足或套餐额度/权益不够。不要自己判断是哪种,照 nextAction.message 转达给用户,不要重试 apply。",
|
|
77
77
|
"SERVER_ERROR": "服务端出错,**不是余额问题**(余额不足是 QUOTA_EXCEEDED)。常见原因是站点侧配置缺失或服务端临时故障。**apply 阶段先别重试**——可能已经提交了,先用 dhVideos.list / clipTasks.list 确认;把 message 和 requestId 一起转达给用户,让他联系服务商。"
|
|
78
78
|
},
|
|
79
79
|
"completionCriteria": "查询类:已如实呈现任务状态或资源列表;任务没跑完就说清它还在哪个阶段,不要拿空的 videoUrl 当「失败」。写入类:用户看过 plan 摘要(含费用说明)并明确同意,apply 已返回任务号,并告诉了用户去哪儿查进度。",
|
package/package.json
CHANGED
package/skills/best-geo/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: best-geo
|
|
3
|
-
description: 通过 Best GEO CLI 查询和维护用户在 GEO 系统里的 GEO 项目、搜索问题、文章、知识库、图片/视频素材,以及定时监控计划——定期问各家 AI 有没有提到、怎么评价用户的品牌;也能现在就拿几个问题去问几家 AI,取回原话、引用来源和拆解词(新增/修改需用户确认)。当用户提到自己的品牌、GEO 项目、搜索问题、文章、知识库或素材,想新建、修改这些内容,或者想持续盯着 AI 有没有推荐自己、定期看 AI 怎么评价自己、查某个监控计划跑完没有,或者想看各家 AI
|
|
3
|
+
description: 通过 Best GEO CLI 查询和维护用户在 GEO 系统里的 GEO 项目、搜索问题、文章、知识库、图片/视频素材,以及定时监控计划——定期问各家 AI 有没有提到、怎么评价用户的品牌;也能现在就拿几个问题去问几家 AI,取回原话、引用来源和拆解词(新增/修改需用户确认)。当用户提到自己的品牌、GEO 项目、搜索问题、文章、知识库或素材,想新建、修改这些内容,或者想持续盯着 AI 有没有推荐自己、定期看 AI 怎么评价自己、查某个监控计划跑完没有,或者想看各家 AI 现在怎么回答某几个问题时使用。也用于数字人视频与剪辑、AI 答案卡、批量写文章、自媒体发布与媒体投稿。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Best GEO
|
|
@@ -43,8 +43,12 @@ best-geo guide get article-task # 要让 AI 批量写一批文章
|
|
|
43
43
|
best-geo guide get scheduled-monitor # 要定期盯 AI 有没有提到你、怎么评价你
|
|
44
44
|
best-geo guide get indexing-query # 现在就拿几个问题去问几家 AI,取回原话、引用来源和拆解词
|
|
45
45
|
best-geo guide get publication # 要把内容发出去/投稿,或查发出去没有、发到哪个链接、花了多少钱
|
|
46
|
+
best-geo guide get video # 要做数字人口播视频、智能剪辑,或查它们的进度
|
|
47
|
+
best-geo guide get answer-card # 要把文章/文案做成多页答案卡(图文),或把现成图片导入成答案卡
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
清单以 `best-geo guide list` 为准,能力的 `guide` 字段就是对应指南名。
|
|
51
|
+
|
|
48
52
|
## 调用业务能力
|
|
49
53
|
|
|
50
54
|
```
|
|
@@ -103,6 +107,8 @@ best-geo call questions.list --input '{"projectId":12,"limit":20}'
|
|
|
103
107
|
|
|
104
108
|
新增和修改**一律不能一步做完**。你对用户目标的理解可能有偏差,而写入不可逆。
|
|
105
109
|
|
|
110
|
+
plan 前要用户定的东西(选哪些问题、写作方向、篇数、频率、画质、要不要打 AI 声明等),**把还缺的一次列全、在一条消息里问完**,用户已经说清楚的不要再问。凑齐了就直接 plan,费用随摘要说,不要再单独确认一次。
|
|
111
|
+
|
|
106
112
|
```
|
|
107
113
|
best-geo plan projects.update --input '{"projectId":12,"name":"新名称"}'
|
|
108
114
|
→ 返回 planId 和 summary(变更前后摘要),此时数据没有任何改动
|
|
@@ -116,6 +122,7 @@ best-geo plan projects.update --input '{"projectId":12,"name":"新名称"}'
|
|
|
116
122
|
|
|
117
123
|
其他规则:
|
|
118
124
|
|
|
125
|
+
- **一件事要拆成多份计划时**(比如传多张图、改多条记录),先把每份都 plan 好,摘要和费用合在一条消息里让用户一次确认,再逐个 apply;不要 plan 一份问一次。某一份 apply 失败只影响它自己,其余照常。
|
|
119
126
|
- 计划 **30 分钟**内有效,且**只能执行一次**。apply 返回后不要重复执行;网络重试拿到的是第一次的结果,不会重复写入。
|
|
120
127
|
- 计划失效(`message` 提到已失效/已过期)说明数据在确认期间被改过或超时了。**重新 plan、把新摘要再给用户确认一次**,不要拿旧 planId 重试。
|
|
121
128
|
- **任务类操作(`questionTasks.*` / `articleTasks.*`)apply 成功不等于事情做完了**:结果里的 `pending: true` 表示任务刚排进后台队列。这时候要做的是**回话告诉用户在跑了**,不是接着查结果——刚提交那一刻一定是空的。更不要因为查不到就再建一个,每建一次都真的多跑一个任务,多出来的那批还得用户回头自己收拾。
|