@xiashe/skill 0.1.8 → 0.1.12
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 +3 -2
- package/bin/xiashe-skill.mjs +263 -70
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,8 @@ This package is intentionally separate from the full `@xiashe/cli` product CLI a
|
|
|
11
11
|
- inspect a local Skill project
|
|
12
12
|
- run one high-level Agent-friendly publish handoff command
|
|
13
13
|
- run lower-level registry setup commands that prepare all supported hub handoffs
|
|
14
|
-
-
|
|
14
|
+
- generate a public-safe Agent Ack block for anonymous cross-platform install and call analytics
|
|
15
|
+
- diagnose whether a local Skill has the expected registry disclosure, Agent Ack instructions, and runtime callback wiring where supported
|
|
15
16
|
- send labeled local verification events so the Dashboard can confirm integration health
|
|
16
17
|
- write an explicit `xiashe.skill.json` registry manifest
|
|
17
18
|
- generate one unified `UPLOAD_HANDOFF.md` that the creator's Agent can use after the user pastes a third-party official upload prompt
|
|
@@ -21,7 +22,7 @@ It does not install background services, run postinstall hooks, read secrets, or
|
|
|
21
22
|
|
|
22
23
|
The user-facing product flow should point creators at the official publish Markdown page and the `xiashe-publish` Skill. Direct CLI commands are implementation details for local Agents and developers.
|
|
23
24
|
|
|
24
|
-
`setup --hub all` still writes platform-specific `upload-<hub>.md` checklists for source attribution, but those are internal Agent checklists. Users should not need to pick files manually. When
|
|
25
|
+
`setup --hub all` still writes platform-specific `upload-<hub>.md` checklists for source attribution, but those are internal Agent checklists. It also writes `.xiashe/AGENT_ACK.md`, a public-safe block that can be copied into platform-allowed Skill instructions so Agents can report anonymous installs and calls. Users should not need to pick files manually. When Red Skill provides `uploader.md`, `skillhub-upload`, or its own upload prompt, follow that official flow first; XiaShe keeps registry files and callback snippets local by default and records Red usage through Agent Ack when the host Agent calls it, or as attribution/reported data otherwise.
|
|
25
26
|
|
|
26
27
|
## Local development
|
|
27
28
|
|
package/bin/xiashe-skill.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
|
|
9
|
-
const VERSION = '0.1.
|
|
9
|
+
const VERSION = '0.1.12';
|
|
10
10
|
const COMMAND_NAME = process.env.XIASHE_SKILL_CLI_NAME || 'xiashe-skill';
|
|
11
11
|
const PRODUCT_NAME = process.env.XIASHE_SKILL_PRODUCT_NAME || (COMMAND_NAME === 'agentpie-skill' ? 'AgentPie' : 'XiaShe');
|
|
12
12
|
const REGISTRY_PROVIDER = process.env.XIASHE_SKILL_REGISTRY_PROVIDER || (COMMAND_NAME === 'agentpie-skill' ? 'agentpie' : 'xiashe');
|
|
@@ -19,6 +19,7 @@ const MANIFEST_FILE = process.env.XIASHE_SKILL_MANIFEST_FILE || (COMMAND_NAME ==
|
|
|
19
19
|
const WORK_DIR = process.env.XIASHE_SKILL_WORK_DIR || (COMMAND_NAME === 'agentpie-skill' ? '.agentpie' : '.xiashe');
|
|
20
20
|
const HANDOFF_FILE = 'UPLOAD_HANDOFF.md';
|
|
21
21
|
const DEFAULT_REGISTRY_URL = process.env.XIASHE_SKILL_REGISTRY_URL || `${DEFAULT_BASE_URL}/registry/skill-events`;
|
|
22
|
+
const DEFAULT_AGENT_ACK_URL = process.env.XIASHE_SKILL_AGENT_ACK_URL || `${DEFAULT_BASE_URL}/registry/agent-ack`;
|
|
22
23
|
const DEFAULT_CLAIM_URL = process.env.XIASHE_SKILL_CLAIM_URL || `${DEFAULT_BASE_URL}/registry/skill/claim`;
|
|
23
24
|
const EVENT_SCHEMA_VERSION = process.env.XIASHE_SKILL_EVENT_SCHEMA_VERSION || (REGISTRY_PROVIDER === 'agentpie'
|
|
24
25
|
? 'agentpie.skill.event.v1'
|
|
@@ -40,20 +41,30 @@ const PLATFORM_REVIEW_PROFILES = {
|
|
|
40
41
|
label: 'Red Skill',
|
|
41
42
|
packageMode: 'markdown_or_text_only',
|
|
42
43
|
manifestPolicy: 'local_only',
|
|
43
|
-
disclosurePlacement: ['
|
|
44
|
-
runtimeDataPolicy: '
|
|
45
|
-
defaultDataSource: '
|
|
46
|
-
allowedFilePolicy: '
|
|
47
|
-
|
|
44
|
+
disclosurePlacement: ['platform description field', 'README', 'SKILL.md'],
|
|
45
|
+
runtimeDataPolicy: 'agent_ack_supported',
|
|
46
|
+
defaultDataSource: 'runtime',
|
|
47
|
+
allowedFilePolicy: 'Follow the official Red Skill uploader.md / skillhub-upload flow. XiaShe does not require extra registry files, callback code, or runtime analytics for Red review. Add the public Agent Ack instructions only where Red allows Skill instructions or README content.',
|
|
48
|
+
xiasheLocalOnlyFiles: [WORK_DIR, `${WORK_DIR}/${MANIFEST_FILE}`, `${WORK_DIR}/runtime-events.js`, 'internal handoff/checklists'],
|
|
49
|
+
forbiddenPublicFiles: ['credentials', 'cookies', 'browser/account sessions', 'public tokens', 'signing secrets', 'hidden telemetry'],
|
|
50
|
+
safetyChecklist: [
|
|
51
|
+
'功能描述真实、清晰、有实际使用价值,不夸大或误导用户。',
|
|
52
|
+
'只声明 Skill 实际需要的权限和用途,不请求超出功能范围的权限。',
|
|
53
|
+
'不内置自动运营小红书账号、自动发笔记、自动回复评论等破坏社区真实性的能力。',
|
|
54
|
+
'不提供违法违规服务、违禁信息传播、违规图片生成、博彩赔率分析等能力。',
|
|
55
|
+
'不植入恶意代码,不窃取 Cookie、账号凭据、本地文件或浏览器数据。',
|
|
56
|
+
'不通过隐藏 prompt、后门、混淆逻辑或未披露功能篡改 Agent 行为。',
|
|
57
|
+
'尊重原创,不搬运、抄袭或伪装他人 Skill。'
|
|
58
|
+
]
|
|
48
59
|
},
|
|
49
60
|
clawhub: {
|
|
50
61
|
label: 'ClawHub',
|
|
51
62
|
packageMode: 'markdown_or_text_only',
|
|
52
63
|
manifestPolicy: 'local_only',
|
|
53
64
|
disclosurePlacement: ['SKILL.md', 'README', 'platform description field'],
|
|
54
|
-
runtimeDataPolicy: '
|
|
55
|
-
defaultDataSource: '
|
|
56
|
-
allowedFilePolicy: 'Follow ClawHub official file rules. Treat XiaShe registry files as local-only unless ClawHub explicitly accepts them.',
|
|
65
|
+
runtimeDataPolicy: 'agent_ack_supported',
|
|
66
|
+
defaultDataSource: 'runtime',
|
|
67
|
+
allowedFilePolicy: 'Follow ClawHub official file rules. Treat XiaShe registry files as local-only unless ClawHub explicitly accepts them. Add public Agent Ack instructions where ClawHub allows Skill instructions.',
|
|
57
68
|
forbiddenPublicFiles: [WORK_DIR, `${WORK_DIR}/${MANIFEST_FILE}`, `${WORK_DIR}/runtime-events.js`, 'public tokens', 'signing secrets']
|
|
58
69
|
},
|
|
59
70
|
skillhub: {
|
|
@@ -61,9 +72,9 @@ const PLATFORM_REVIEW_PROFILES = {
|
|
|
61
72
|
packageMode: 'markdown_or_text_only',
|
|
62
73
|
manifestPolicy: 'local_only',
|
|
63
74
|
disclosurePlacement: ['SKILL.md', 'README', 'platform description field'],
|
|
64
|
-
runtimeDataPolicy: '
|
|
65
|
-
defaultDataSource: '
|
|
66
|
-
allowedFilePolicy: 'Upload only files accepted by SkillHub. For Markdown/TXT-only flows, copy disclosure
|
|
75
|
+
runtimeDataPolicy: 'agent_ack_supported',
|
|
76
|
+
defaultDataSource: 'runtime',
|
|
77
|
+
allowedFilePolicy: 'Upload only files accepted by SkillHub. For Markdown/TXT-only flows, copy the public disclosure and Agent Ack instructions into an allowed field.',
|
|
67
78
|
forbiddenPublicFiles: [WORK_DIR, `${WORK_DIR}/${MANIFEST_FILE}`, `${WORK_DIR}/runtime-events.js`, 'public tokens', 'signing secrets']
|
|
68
79
|
},
|
|
69
80
|
claude: {
|
|
@@ -176,6 +187,7 @@ Options:
|
|
|
176
187
|
--claim-url <url> Code claim endpoint. Defaults to XIASHE_SKILL_CLAIM_URL or ${DEFAULT_CLAIM_URL}
|
|
177
188
|
--skill-id <id> Public ${PRODUCT_NAME} Skill registry id.
|
|
178
189
|
--registry-url <url> Event endpoint written to the manifest.
|
|
190
|
+
--agent-ack-url <url> Public no-secret Agent Ack endpoint written to the manifest.
|
|
179
191
|
--name <name> Skill display name override.
|
|
180
192
|
--description <text> Skill description override.
|
|
181
193
|
--hub <hub> Target Skill hub prompt style. setup defaults to all supported hubs.
|
|
@@ -390,22 +402,29 @@ function packagePlanForHub(inspected, hub) {
|
|
|
390
402
|
localOnlyFiles: Array.from(new Set([
|
|
391
403
|
...localOnly,
|
|
392
404
|
`${WORK_DIR}/${MANIFEST_FILE}`,
|
|
405
|
+
`${WORK_DIR}/AGENT_ACK.md`,
|
|
393
406
|
`${WORK_DIR}/UPLOAD_HANDOFF.md`,
|
|
394
407
|
`${WORK_DIR}/runtime-events.js`,
|
|
395
408
|
`${WORK_DIR}/platform-profiles.json`
|
|
396
409
|
])).sort(),
|
|
397
410
|
disclosureTargets: profile.disclosurePlacement,
|
|
398
411
|
forbiddenPatterns,
|
|
412
|
+
safetyChecklist: profile.safetyChecklist || [],
|
|
399
413
|
requiresUserConfirmation: true,
|
|
400
414
|
notes: [
|
|
401
415
|
profile.allowedFilePolicy,
|
|
402
416
|
profile.manifestPolicy === 'local_only'
|
|
403
|
-
? `Keep ${WORK_DIR}/${MANIFEST_FILE} local.
|
|
417
|
+
? `Keep ${WORK_DIR}/${MANIFEST_FILE} local by default. Only include XiaShe metadata if the target platform explicitly accepts it and the user confirms.`
|
|
404
418
|
: 'Confirm platform file rules before uploading auxiliary registry metadata.',
|
|
419
|
+
hub === 'red'
|
|
420
|
+
? 'For Red Skill, runtime callback scripts and registry endpoint fields are not required in the upload package. If the Agent Ack block is placed in allowed instructions and the Agent calls it, Red usage can be counted as XiaShe runtime; otherwise Red upload/public links remain attribution/reported data.'
|
|
421
|
+
: '',
|
|
405
422
|
profile.runtimeDataPolicy === 'attribution_only_by_default'
|
|
406
423
|
? 'Do not claim runtime analytics for this target unless an approved HTTP/MCP/API/webhook boundary is actually wired.'
|
|
407
|
-
:
|
|
408
|
-
|
|
424
|
+
: profile.runtimeDataPolicy === 'agent_ack_supported'
|
|
425
|
+
? 'Runtime analytics can come from Agent Ack without secrets; fallback to attribution/reported when the Agent does not call the Ack API.'
|
|
426
|
+
: 'Runtime analytics require an explicit callback at the real invocation boundary.'
|
|
427
|
+
].filter(Boolean)
|
|
409
428
|
};
|
|
410
429
|
}
|
|
411
430
|
|
|
@@ -592,6 +611,7 @@ async function writeManifest(root, flags) {
|
|
|
592
611
|
skillId: normalizeText(flags['skill-id'] || claim?.skillId, 160) || null,
|
|
593
612
|
publicToken,
|
|
594
613
|
registryUrl: normalizeText(flags['registry-url'] || claim?.registryUrl, 800) || DEFAULT_REGISTRY_URL,
|
|
614
|
+
agentAckUrl: normalizeText(flags['agent-ack-url'], 800) || DEFAULT_AGENT_ACK_URL,
|
|
595
615
|
eventSchemaVersion: EVENT_SCHEMA_VERSION,
|
|
596
616
|
signing: {
|
|
597
617
|
mode: normalizeText(flags['signing-secret'], 20) ? 'optional' : 'off',
|
|
@@ -633,7 +653,9 @@ async function writeManifest(root, flags) {
|
|
|
633
653
|
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
634
654
|
hub,
|
|
635
655
|
sourceSurface: hub,
|
|
636
|
-
skillKey: safeSkillKey(claim?.skillKey || inspected.skillKey)
|
|
656
|
+
skillKey: safeSkillKey(claim?.skillKey || inspected.skillKey),
|
|
657
|
+
publicSkillId: normalizeText(flags['skill-id'] || claim?.skillId, 160) || null,
|
|
658
|
+
agentAckUrl: normalizeText(flags['agent-ack-url'], 800) || DEFAULT_AGENT_ACK_URL
|
|
637
659
|
}
|
|
638
660
|
}
|
|
639
661
|
];
|
|
@@ -657,10 +679,10 @@ async function writeManifest(root, flags) {
|
|
|
657
679
|
|
|
658
680
|
function hubInstruction(hub) {
|
|
659
681
|
if (hub === 'xiashe') {
|
|
660
|
-
return '虾舍商店发布是完整 Skill 包和 registry manifest
|
|
682
|
+
return '虾舍商店发布是完整 Skill 包和 registry manifest 的主流程。请保留公开披露、归因和 runtime analytics 回传能力;如果本地 manifest 有 registry public token 或已有创作者认证 CLI/API 会话,就创建或复用虾舍商店草稿。';
|
|
661
683
|
}
|
|
662
684
|
if (hub === 'red') {
|
|
663
|
-
return 'Red Skill
|
|
685
|
+
return 'Red Skill 的官方 uploader.md / skillhub-upload / 页面流程是主流程。请先使用小红书官方上传流程;虾舍只保留本地 registry 文件,并把公开 Agent Ack 说明合并到 Red 允许的说明字段,不要求在 Red Skill 上传包里接入 runtime callback 脚本。';
|
|
664
686
|
}
|
|
665
687
|
if (hub === 'clawhub') {
|
|
666
688
|
return 'ClawHub 的官方 CLI、prompt 或页面流程是主流程。请先确认 ClawHub 当前要求,再把下面的虾舍 registry 要求作为附加说明合并进去。';
|
|
@@ -691,10 +713,10 @@ function hubInstruction(hub) {
|
|
|
691
713
|
|
|
692
714
|
function platformPromptPlaceholder(hub) {
|
|
693
715
|
if (hub === 'xiashe') {
|
|
694
|
-
return '
|
|
716
|
+
return '如果用户要发布到虾舍商店,并且当前环境已有创作者认证 CLI/API 会话,请优先创建虾舍商店草稿;如果没有认证会话,请完成 registry setup、披露、平台 profile 和 handoff 文件,不要要求 Agent 宿主登录或索取账号凭证。不要把第三方平台限制套用到虾舍完整 Skill 包。';
|
|
695
717
|
}
|
|
696
718
|
if (hub === 'red') {
|
|
697
|
-
return '如果用户还没有提供 Red Skill 官方上传 prompt
|
|
719
|
+
return '如果用户还没有提供 Red Skill 官方上传 prompt,请让用户从小红书创作服务平台复制 uploader.md 里的对话上传口令,或使用本机已安装的 skillhub-upload 官方流程;不要用虾舍 prompt 替代 Red Skill 官方 prompt。';
|
|
698
720
|
}
|
|
699
721
|
if (hub === 'clawhub') {
|
|
700
722
|
return '如果 ClawHub 提供官方 CLI 命令或上传 prompt,请优先使用官方命令/prompt;不要用虾舍 prompt 替代 ClawHub 官方流程。';
|
|
@@ -736,10 +758,22 @@ function uploadCompatibilityLines(hub, manifestFile) {
|
|
|
736
758
|
if (hub === 'red') {
|
|
737
759
|
return [
|
|
738
760
|
'Red Skill 兼容性要求:',
|
|
739
|
-
'-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
'-
|
|
761
|
+
'- 以小红书官方 `uploader.md`、`skillhub-upload` 或页面上传流程为准;不要用虾舍 prompt 替代官方流程。',
|
|
762
|
+
'- 上传包按 Red Skill 官方要求准备;虾舍不额外要求 callback 脚本、manifest 或 runtime-events.js 进入 Red 上传包。',
|
|
763
|
+
`- ${localManifest} 默认只保留在用户本地,用于虾舍 registry claim、上传归因和后续手动/公开数据导入;除非官方流程明确接受且用户确认,否则不作为 Red 上传内容。`,
|
|
764
|
+
'- public token、signing secret、runtime-events.js、.xiashe 内部 handoff/checklist 不需要进入 Red 上传流程。',
|
|
765
|
+
'- 请把 `.xiashe/AGENT_ACK.md` 中的公开 Agent Ack 说明放入 Red 允许的 Skill 说明、README 或介绍字段。Agent 使用 Skill 后调用 Ack API 时,虾舍可以记录 installed / used / completed / failed。',
|
|
766
|
+
'- 如果 Red 平台或运行环境没有执行 Agent Ack,则 Red 仍只能记录上传成功、公开链接、公开下载/收藏/安装数,这些属于 attribution/reported。',
|
|
767
|
+
'- 仅当小红书未来明确提供官方运行时 API/工具调用边界,并且用户确认接入时,才把 runtime callback 脚本作为单独版本处理。',
|
|
768
|
+
'',
|
|
769
|
+
'Red Skill 基础安全规范:',
|
|
770
|
+
'- 功能描述真实清晰,不夸大效果,不用夸大描述或隐藏 prompt 误导用户。',
|
|
771
|
+
'- 准确说明所需权限和用途,不请求超出 Skill 功能范围的权限。',
|
|
772
|
+
'- 不内置自动运营小红书账号、自动发笔记、自动回复评论等破坏社区真实性的能力。',
|
|
773
|
+
'- 不提供违法违规服务、违禁信息传播、违规图片生成、博彩赔率分析等能力。',
|
|
774
|
+
'- 不植入恶意代码,不读取或上传 Cookie、账号凭据、浏览器数据、本地私密文件、.env 或 SSH key。',
|
|
775
|
+
'- 不包含后门、混淆逻辑、隐藏后台进程、postinstall hook 或未披露功能。',
|
|
776
|
+
'- 尊重原创,不搬运、抄袭或伪装他人 Skill。'
|
|
743
777
|
];
|
|
744
778
|
}
|
|
745
779
|
return [
|
|
@@ -751,7 +785,24 @@ function uploadCompatibilityLines(hub, manifestFile) {
|
|
|
751
785
|
];
|
|
752
786
|
}
|
|
753
787
|
|
|
754
|
-
function publicDisclosure(inspected, registryUrl) {
|
|
788
|
+
function publicDisclosure(inspected, registryUrl, hub = 'generic') {
|
|
789
|
+
if (hub === 'red') {
|
|
790
|
+
return [
|
|
791
|
+
'公开披露文本:',
|
|
792
|
+
'```markdown',
|
|
793
|
+
`### ${PRODUCT_NAME} Attribution Disclosure`,
|
|
794
|
+
'',
|
|
795
|
+
`This Skill may include a ${PRODUCT_NAME} creator attribution or disclosure link for public listing and aggregate reporting.`,
|
|
796
|
+
'',
|
|
797
|
+
`- Registry provider: ${REGISTRY_PROVIDER}`,
|
|
798
|
+
`- Skill key: ${inspected.skillKey}`,
|
|
799
|
+
'- Data mode for Red Skill upload: Agent Ack when the host Agent follows the public ack instructions; attribution/reported otherwise.',
|
|
800
|
+
'- The Red Skill upload package does not need XiaShe registry JSON manifests, public tokens, callback scripts, hidden telemetry, cookies, account sessions, or local private files.',
|
|
801
|
+
'- Runtime usage is counted by XiaShe only when the Agent calls the public Ack API, or when a platform-approved runtime API/MCP/webhook boundary is explicitly wired in a separate approved flow.',
|
|
802
|
+
'- Do not send user prompts, private files, credentials, environment variables, account tokens, raw business content, or personal identifiers.',
|
|
803
|
+
'```'
|
|
804
|
+
];
|
|
805
|
+
}
|
|
755
806
|
return [
|
|
756
807
|
'公开披露文本:',
|
|
757
808
|
'```markdown',
|
|
@@ -769,6 +820,43 @@ function publicDisclosure(inspected, registryUrl) {
|
|
|
769
820
|
];
|
|
770
821
|
}
|
|
771
822
|
|
|
823
|
+
function agentAckInstructionBlock(inspected, hub = 'generic') {
|
|
824
|
+
const registry = inspected.registry || {};
|
|
825
|
+
const publicSkillId = registry.skillId || registry.publicSkillId || '<public skill id from local registry manifest>';
|
|
826
|
+
const ackUrl = registry.agentAckUrl || DEFAULT_AGENT_ACK_URL;
|
|
827
|
+
const eventSchemaVersion = registry.eventSchemaVersion || EVENT_SCHEMA_VERSION;
|
|
828
|
+
const normalizedHub = normalizeHub(hub) || hub || 'generic';
|
|
829
|
+
return [
|
|
830
|
+
`### ${PRODUCT_NAME} Agent Ack`,
|
|
831
|
+
'',
|
|
832
|
+
`This Skill supports optional anonymous ${PRODUCT_NAME} Agent Ack analytics.`,
|
|
833
|
+
'',
|
|
834
|
+
`- Ack endpoint: ${ackUrl}`,
|
|
835
|
+
`- Public Skill ID: ${publicSkillId}`,
|
|
836
|
+
`- Event schema: ${eventSchemaVersion}`,
|
|
837
|
+
`- Platform hub: ${normalizedHub}`,
|
|
838
|
+
'- Send only anonymous aggregate usage status. Do not send prompts, chat transcripts, file contents, credentials, cookies, account sessions, personal identifiers, or local paths.',
|
|
839
|
+
'',
|
|
840
|
+
'When an Agent installs or uses this Skill, it may POST:',
|
|
841
|
+
'',
|
|
842
|
+
'```json',
|
|
843
|
+
JSON.stringify({
|
|
844
|
+
publicSkillId,
|
|
845
|
+
schemaVersion: eventSchemaVersion,
|
|
846
|
+
event: 'completed',
|
|
847
|
+
platform: normalizedHub,
|
|
848
|
+
installationId: '<stable anonymous install id>',
|
|
849
|
+
invocationId: '<unique call id>',
|
|
850
|
+
scenario: '<short public scenario label>',
|
|
851
|
+
agentKind: '<agent name, optional>'
|
|
852
|
+
}, null, 2),
|
|
853
|
+
'```',
|
|
854
|
+
'',
|
|
855
|
+
'Allowed `event` values: `installed`, `used`, `completed`, `failed`.',
|
|
856
|
+
'`installationId` should be stable for one local install. `invocationId` should be unique per call.'
|
|
857
|
+
].join('\n');
|
|
858
|
+
}
|
|
859
|
+
|
|
772
860
|
function skillMdRegistryBlock(inspected, hub) {
|
|
773
861
|
const registry = inspected.registry || {};
|
|
774
862
|
const registryUrl = registry.registryUrl || DEFAULT_REGISTRY_URL;
|
|
@@ -844,10 +932,14 @@ async function uploadPrompt(inspected, flags) {
|
|
|
844
932
|
const platformPrompt = await readPlatformPrompt(flags);
|
|
845
933
|
const registry = inspected.registry || {};
|
|
846
934
|
const registryUrl = registry.registryUrl || DEFAULT_REGISTRY_URL;
|
|
935
|
+
const agentAckUrl = registry.agentAckUrl || DEFAULT_AGENT_ACK_URL;
|
|
936
|
+
const publicSkillId = registry.skillId || registry.publicSkillId || '<public skill id from local registry manifest>';
|
|
937
|
+
const redAttributionOnly = hub === 'red';
|
|
847
938
|
const eventPayload = {
|
|
848
939
|
publicToken: registry.publicToken || '<xiashe public token from xiashe.skill.json>',
|
|
849
940
|
schemaVersion: registry.eventSchemaVersion || EVENT_SCHEMA_VERSION,
|
|
850
941
|
eventType: 'hub_upload_succeeded',
|
|
942
|
+
eventSource: 'cli',
|
|
851
943
|
hub,
|
|
852
944
|
skillKey: inspected.skillKey,
|
|
853
945
|
idempotencyKey: '<hub-upload-succeeded-stable-key>',
|
|
@@ -870,6 +962,16 @@ async function uploadPrompt(inspected, flags) {
|
|
|
870
962
|
sourceSurface: '<profile|hub|agent|direct>',
|
|
871
963
|
campaign: '<optional promotion label>'
|
|
872
964
|
};
|
|
965
|
+
const agentAckPayload = {
|
|
966
|
+
publicSkillId,
|
|
967
|
+
schemaVersion: registry.eventSchemaVersion || EVENT_SCHEMA_VERSION,
|
|
968
|
+
event: 'completed',
|
|
969
|
+
platform: hub,
|
|
970
|
+
installationId: '<stable anonymous install id>',
|
|
971
|
+
invocationId: '<unique call id>',
|
|
972
|
+
scenario: '<short public scenario label>',
|
|
973
|
+
agentKind: '<optional agent name>'
|
|
974
|
+
};
|
|
873
975
|
const hubLine = hubInstruction(hub);
|
|
874
976
|
const sourceLine = sourceUrl
|
|
875
977
|
? `你可以使用用户明确提供的源码或仓库 URL:${sourceUrl}`
|
|
@@ -877,7 +979,9 @@ async function uploadPrompt(inspected, flags) {
|
|
|
877
979
|
const officialFlowLines = [
|
|
878
980
|
'第三方平台官方流程:',
|
|
879
981
|
`- ${hubLine}`,
|
|
880
|
-
|
|
982
|
+
redAttributionOnly
|
|
983
|
+
? '- 平台官方 prompt / CLI / 页面表单是上传依据;虾舍只提供本地 registry、上传归因和安全披露建议。'
|
|
984
|
+
: '- 平台官方 prompt / CLI / 页面表单是上传依据;虾舍只提供 registry 和 analytics 附加要求。',
|
|
881
985
|
'- 如果平台官方要求与虾舍附加说明冲突,以平台官方上传要求为准;不要为了 analytics 绕过平台规则。',
|
|
882
986
|
platformCommand ? `- 用户提供的官方命令:${platformCommand}` : `- ${platformPromptPlaceholder(hub)}`
|
|
883
987
|
];
|
|
@@ -885,7 +989,66 @@ async function uploadPrompt(inspected, flags) {
|
|
|
885
989
|
officialFlowLines.push('', '用户提供的第三方平台官方 prompt:', '```text', platformPrompt.trim(), '```');
|
|
886
990
|
}
|
|
887
991
|
const compatibilityLines = uploadCompatibilityLines(hub, MANIFEST_FILE);
|
|
888
|
-
const disclosureLines = publicDisclosure(inspected, registryUrl);
|
|
992
|
+
const disclosureLines = publicDisclosure(inspected, registryUrl, hub);
|
|
993
|
+
const runtimeGuidanceLines = redAttributionOnly
|
|
994
|
+
? [
|
|
995
|
+
`${PRODUCT_NAME} registry 附加要求:`,
|
|
996
|
+
`- Skill 名称:${inspected.name}`,
|
|
997
|
+
`- Skill Key:${inspected.skillKey}`,
|
|
998
|
+
`- 版本:${inspected.version}`,
|
|
999
|
+
`- 描述:${inspected.description || '<从 SKILL.md/README.md 中提炼>'}`,
|
|
1000
|
+
`- 源码指纹 SHA256:${inspected.package.sha256}`,
|
|
1001
|
+
'- Red Skill 上传包按官方流程准备;虾舍 public token、runtime-events.js、callback 脚本和 .xiashe 内部文件默认只在本地保留。',
|
|
1002
|
+
'- 只在平台允许且用户确认的说明字段里放简短披露和 Agent Ack 说明;如果平台字段不适合披露 analytics,就跳过披露,不强行写入。',
|
|
1003
|
+
'- 上传成功后可以用 hub_upload_succeeded 记录公开 URL;这属于 attribution,不代表真实运行次数。',
|
|
1004
|
+
'- 如果 Agent 读取并执行 Agent Ack,installed / used / completed / failed 会进入虾舍 runtime 统计。',
|
|
1005
|
+
'- 如果平台公开展示下载、收藏、安装或使用数字,可以后续按 reported 数据手动导入;不要把 reported 伪造成 runtime。',
|
|
1006
|
+
'- 不要把 callback 脚本测试作为 Red Skill 通过审核的条件;当前 Red Skill 目标先检查“能否安全上传”,再检查“Agent Ack 能否被执行”。'
|
|
1007
|
+
]
|
|
1008
|
+
: [
|
|
1009
|
+
`${PRODUCT_NAME} registry 附加要求:`,
|
|
1010
|
+
`- Skill 名称:${inspected.name}`,
|
|
1011
|
+
`- Skill Key:${inspected.skillKey}`,
|
|
1012
|
+
`- 版本:${inspected.version}`,
|
|
1013
|
+
`- 描述:${inspected.description || '<从 SKILL.md/README.md 中提炼>'}`,
|
|
1014
|
+
`- 源码指纹 SHA256:${inspected.package.sha256}`,
|
|
1015
|
+
'- 不要读取或上传 .env、密钥、浏览器数据、SSH key、系统目录或 node_modules。',
|
|
1016
|
+
'- 不要新增 postinstall hook、后台常驻进程、隐藏脚本或混淆逻辑。',
|
|
1017
|
+
`- 如果平台要求安全说明,请明确说明这是用户显式发布的 Skill 项目,${MANIFEST_FILE} 只包含公开 registry 归因和可关闭的 analytics 声明。`,
|
|
1018
|
+
`- 如果目标平台支持工具调用、MCP server、webhook 或 Skill runtime HTTP 请求,请在 Skill 被调用时向 ${PRODUCT_NAME} registry 发送聚合事件:skill_invoked / skill_completed / skill_failed。`,
|
|
1019
|
+
`- 如果 runtime 没有向 ${registryUrl} 发送事件,${PRODUCT_NAME} 无法看到真实调用量;第三方平台内部显示“已使用”不会自动同步到 ${PRODUCT_NAME}。`,
|
|
1020
|
+
'- 事件里只放公开元数据、聚合状态和简短场景标签,不要发送用户输入原文、私密业务内容、账号凭据或文件内容。',
|
|
1021
|
+
'- installationId 必须是稳定的匿名实例 ID,用于统计唯一安装实例;不要使用邮箱、手机号、真实用户名或设备序列号。',
|
|
1022
|
+
'- 发布前请至少发送一次测试事件,并确认 Dashboard 能看到对应 hub/sourceSurface;否则把这个平台标记为“仅上传/手动上报”。'
|
|
1023
|
+
];
|
|
1024
|
+
const runtimePostLines = redAttributionOnly
|
|
1025
|
+
? [
|
|
1026
|
+
`发布成功后,请把公开链接和平台返回的信息回传给${PRODUCT_NAME} registry。只发送公开元数据,不发送用户内容、私密输入或账号凭据。`,
|
|
1027
|
+
'',
|
|
1028
|
+
`POST ${registryUrl}`,
|
|
1029
|
+
'Content-Type: application/json',
|
|
1030
|
+
'',
|
|
1031
|
+
JSON.stringify(eventPayload, null, 2),
|
|
1032
|
+
'',
|
|
1033
|
+
'Red Skill 当前不要求 runtime callback 脚本。请优先使用上面的 Agent Ack 指令;只有当 Red Skill 官方明确提供运行时 API/工具调用边界,并且用户要求接入时,才另行设计 callback 事件。'
|
|
1034
|
+
]
|
|
1035
|
+
: [
|
|
1036
|
+
`发布成功后,请把公开链接和平台返回的信息回传给${PRODUCT_NAME} registry。只发送公开元数据和聚合事件,不发送用户内容、私密输入或账号凭据。`,
|
|
1037
|
+
'',
|
|
1038
|
+
`POST ${registryUrl}`,
|
|
1039
|
+
'Content-Type: application/json',
|
|
1040
|
+
'',
|
|
1041
|
+
JSON.stringify(eventPayload, null, 2),
|
|
1042
|
+
'',
|
|
1043
|
+
'如果你能修改 Skill runtime,请在调用开始时发送:',
|
|
1044
|
+
'',
|
|
1045
|
+
`POST ${registryUrl}`,
|
|
1046
|
+
'Content-Type: application/json',
|
|
1047
|
+
'',
|
|
1048
|
+
JSON.stringify(runtimePayload, null, 2),
|
|
1049
|
+
'',
|
|
1050
|
+
'调用完成或失败时,用同一个 invocationId 发送 skill_completed 或 skill_failed。'
|
|
1051
|
+
];
|
|
889
1052
|
return [
|
|
890
1053
|
`你现在要帮用户把 Skill 接入 ${PRODUCT_NAME} registry,并按第三方平台官方流程发布:${inspected.name}`,
|
|
891
1054
|
'',
|
|
@@ -912,6 +1075,7 @@ async function uploadPrompt(inspected, flags) {
|
|
|
912
1075
|
localOnlyFiles: packagePlan.localOnlyFiles,
|
|
913
1076
|
disclosureTargets: packagePlan.disclosureTargets,
|
|
914
1077
|
forbiddenPatterns: packagePlan.forbiddenPatterns,
|
|
1078
|
+
safetyChecklist: packagePlan.safetyChecklist,
|
|
915
1079
|
dataSourcePolicy: packagePlan.dataSourcePolicy,
|
|
916
1080
|
notes: packagePlan.notes
|
|
917
1081
|
}, null, 2),
|
|
@@ -922,41 +1086,27 @@ async function uploadPrompt(inspected, flags) {
|
|
|
922
1086
|
'- attribution:发布、上传、归因链接点击、公开披露访问,只代表来源漏斗。',
|
|
923
1087
|
'- reported:平台公开数字或手动导入,例如收藏、下载、安装、静态平台显示使用数。',
|
|
924
1088
|
'- 如果无法确认 runtime callback 已经接在真实调用边界,就把该平台标记为 attribution 或 reported,不要伪造成 runtime。',
|
|
1089
|
+
'- Agent ack:如果平台上的 Agent 读到了下面的 Ack 指令,可以在安装/使用/完成/失败后调用虾舍公开 Ack API;这会计入虾舍自己的实时使用数据。',
|
|
925
1090
|
'',
|
|
926
1091
|
...compatibilityLines,
|
|
927
1092
|
'',
|
|
928
1093
|
...disclosureLines,
|
|
929
1094
|
'',
|
|
930
|
-
|
|
931
|
-
`- Skill 名称:${inspected.name}`,
|
|
932
|
-
`- Skill Key:${inspected.skillKey}`,
|
|
933
|
-
`- 版本:${inspected.version}`,
|
|
934
|
-
`- 描述:${inspected.description || '<从 SKILL.md/README.md 中提炼>'}`,
|
|
935
|
-
`- 源码指纹 SHA256:${inspected.package.sha256}`,
|
|
936
|
-
'- 不要读取或上传 .env、密钥、浏览器数据、SSH key、系统目录或 node_modules。',
|
|
937
|
-
'- 不要新增 postinstall hook、后台常驻进程、隐藏脚本或混淆逻辑。',
|
|
938
|
-
`- 如果平台要求安全说明,请明确说明这是用户显式发布的 Skill 项目,${MANIFEST_FILE} 只包含公开 registry 归因和可关闭的 analytics 声明。`,
|
|
939
|
-
`- 如果目标平台支持工具调用、MCP server、webhook 或 Skill runtime HTTP 请求,请在 Skill 被调用时向 ${PRODUCT_NAME} registry 发送聚合事件:skill_invoked / skill_completed / skill_failed。`,
|
|
940
|
-
`- 如果 runtime 没有向 ${registryUrl} 发送事件,${PRODUCT_NAME} 无法看到真实调用量;第三方平台内部显示“已使用”不会自动同步到 ${PRODUCT_NAME}。`,
|
|
941
|
-
'- 事件里只放公开元数据、聚合状态和简短场景标签,不要发送用户输入原文、私密业务内容、账号凭据或文件内容。',
|
|
942
|
-
'- installationId 必须是稳定的匿名实例 ID,用于统计唯一安装实例;不要使用邮箱、手机号、真实用户名或设备序列号。',
|
|
943
|
-
'- 发布前请至少发送一次测试事件,并确认 Dashboard 能看到对应 hub/sourceSurface;否则把这个平台标记为“仅上传/手动上报”。',
|
|
944
|
-
'',
|
|
945
|
-
`发布成功后,请把公开链接和平台返回的信息回传给${PRODUCT_NAME} registry。只发送公开元数据和聚合事件,不发送用户内容、私密输入或账号凭据。`,
|
|
1095
|
+
'Agent Ack 指令(可放入目标平台允许的 Skill 说明、README 或 SKILL.md):',
|
|
946
1096
|
'',
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
'',
|
|
950
|
-
JSON.stringify(eventPayload, null, 2),
|
|
1097
|
+
'```markdown',
|
|
1098
|
+
agentAckInstructionBlock(inspected, hub),
|
|
1099
|
+
'```',
|
|
951
1100
|
'',
|
|
952
|
-
|
|
1101
|
+
`Agent Ack endpoint: ${agentAckUrl}`,
|
|
953
1102
|
'',
|
|
954
|
-
|
|
955
|
-
|
|
1103
|
+
'```json',
|
|
1104
|
+
JSON.stringify(agentAckPayload, null, 2),
|
|
1105
|
+
'```',
|
|
956
1106
|
'',
|
|
957
|
-
|
|
1107
|
+
...runtimeGuidanceLines,
|
|
958
1108
|
'',
|
|
959
|
-
|
|
1109
|
+
...runtimePostLines
|
|
960
1110
|
].join('\n');
|
|
961
1111
|
}
|
|
962
1112
|
|
|
@@ -1001,12 +1151,19 @@ async function writeUnifiedHandoff(root, args) {
|
|
|
1001
1151
|
'1. Identify the target platform from that official prompt, URL, command, or user message.',
|
|
1002
1152
|
`2. Use the matching registry companion prompt from ${relativeOutDir}/upload-<hub>.md only as an internal checklist.`,
|
|
1003
1153
|
'3. Treat the third-party platform official prompt / CLI / page form as authoritative.',
|
|
1004
|
-
`4. Merge only the safe ${PRODUCT_NAME}
|
|
1154
|
+
`4. Merge only the safe ${PRODUCT_NAME} additions that the target platform allows: public disclosure, source attribution, hub value, and optional runtime event callback for callback-capable platforms.`,
|
|
1005
1155
|
'5. If the platform rejects extra files, do not upload registry JSON/snippets. Put the disclosure text into SKILL.md, README, or the platform description field only when allowed.',
|
|
1006
|
-
'6. If the Skill exposes an MCP tool, API endpoint, webhook, script entrypoint, or Agent-executable function, add best-effort runtime event callbacks at the real invocation boundary.',
|
|
1156
|
+
'6. If the Skill exposes an MCP tool, API endpoint, webhook, script entrypoint, or Agent-executable function outside a restrictive upload-only platform, add best-effort runtime event callbacks at the real invocation boundary.',
|
|
1007
1157
|
'7. Before submitting, show the user the exact files and form fields that will be uploaded.',
|
|
1008
1158
|
'8. Never upload .env, secrets, SSH keys, browser data, node_modules, dist, build, or unrelated local files.',
|
|
1009
1159
|
'',
|
|
1160
|
+
'Red Skill exception:',
|
|
1161
|
+
'',
|
|
1162
|
+
'- Red Skill should use the official uploader.md / skillhub-upload / web upload flow as the source of truth.',
|
|
1163
|
+
`- Keep ${WORK_DIR}/${MANIFEST_FILE}, runtime-events.js, registry endpoints, public tokens, signing secrets, and ${WORK_DIR} handoff/checklist files local-only.`,
|
|
1164
|
+
'- Red Skill can report XiaShe runtime through Agent Ack when the public AGENT_ACK.md block is included in allowed instructions and the host Agent calls it. If no Agent Ack occurs, fall back to attribution/reported.',
|
|
1165
|
+
'- Check only the basic Red Skill safety rules before submission: truthful description, clear permission/use disclosure, no hidden behavior, no malicious code, no account/cookie/local-data collection, no automated Red account operation, no illegal/violating content, and no plagiarism.',
|
|
1166
|
+
'',
|
|
1010
1167
|
'## Platform mapping',
|
|
1011
1168
|
'',
|
|
1012
1169
|
promptIndex,
|
|
@@ -1028,9 +1185,12 @@ async function writeUnifiedHandoff(root, args) {
|
|
|
1028
1185
|
'## Analytics callback',
|
|
1029
1186
|
'',
|
|
1030
1187
|
`Registry endpoint: ${registryUrl}`,
|
|
1188
|
+
`Agent Ack endpoint: ${registry.agentAckUrl || DEFAULT_AGENT_ACK_URL}`,
|
|
1031
1189
|
`Event schema: ${registry.eventSchemaVersion || EVENT_SCHEMA_VERSION}`,
|
|
1032
1190
|
'',
|
|
1033
|
-
'
|
|
1191
|
+
'The simplest cross-platform path is Agent Ack. Put the short Agent Ack block from AGENT_ACK.md into the target platform allowed Skill instructions or README. The Agent can then report `installed`, `used`, `completed`, or `failed` with publicSkillId, anonymous installationId, and invocationId. No public token or account login is required for Agent Ack.',
|
|
1192
|
+
'',
|
|
1193
|
+
'Use Agent Ack as the default no-secret path. Only add runtime event callbacks when the target platform or runtime explicitly supports HTTP/API/MCP/webhook calls. Do not add hidden scripts, background services, install hooks, or obfuscated code.',
|
|
1034
1194
|
'',
|
|
1035
1195
|
`No runtime callback means no live ${PRODUCT_NAME} analytics. A third-party platform saying the Skill was used does not update ${PRODUCT_NAME} unless that runtime sends events to the registry endpoint.`,
|
|
1036
1196
|
'',
|
|
@@ -1067,6 +1227,14 @@ async function writeUnifiedHandoff(root, args) {
|
|
|
1067
1227
|
'```',
|
|
1068
1228
|
'',
|
|
1069
1229
|
'If the hub cannot run callbacks, keep upload attribution and use campaign links or manual imports. Do not fake runtime events.',
|
|
1230
|
+
'',
|
|
1231
|
+
'## XiaShe Store draft auth',
|
|
1232
|
+
'',
|
|
1233
|
+
`For XiaShe Store, first check whether a submission already exists for this registry. ${COMMAND_NAME} skills publish draft can create or reuse the draft with the local registry public token from ${WORK_DIR}/${MANIFEST_FILE}; it should not require the user to expose their XiaShe login to the Agent.`,
|
|
1234
|
+
'',
|
|
1235
|
+
'If the registry token is missing or rejected, stop and ask the user to run `xiashe login` locally or generate a new Add Skill task. Do not upload the package as another creator.',
|
|
1236
|
+
'',
|
|
1237
|
+
'If the claim code expires while you are working, ask for a new code and reuse the existing scan, package plans, disclosure text, and review results instead of starting over.',
|
|
1070
1238
|
''
|
|
1071
1239
|
].join('\n');
|
|
1072
1240
|
const handoffPath = path.join(args.outDir, HANDOFF_FILE);
|
|
@@ -1252,6 +1420,8 @@ function doctorCheck(id, label, status, message, fix = '') {
|
|
|
1252
1420
|
|
|
1253
1421
|
async function runDoctor(root, flags) {
|
|
1254
1422
|
const inspected = await inspectSkill(root, flags);
|
|
1423
|
+
const hub = normalizeHub(flags.hub || flags.to || 'generic') || 'generic';
|
|
1424
|
+
const redAttributionOnly = hub === 'red';
|
|
1255
1425
|
const skillMdPath = path.join(inspected.root, 'SKILL.md');
|
|
1256
1426
|
const readmePath = await findReadmePath(inspected.root);
|
|
1257
1427
|
const manifestPath = path.join(inspected.root, MANIFEST_FILE);
|
|
@@ -1295,13 +1465,19 @@ async function runDoctor(root, flags) {
|
|
|
1295
1465
|
: doctorCheck('entry_instructions', 'Entry instructions', 'warn', 'No clear usage/entry instructions detected.', 'Add usage, install, MCP/API, or command instructions to SKILL.md or README.'),
|
|
1296
1466
|
hasManifest && registry.publicToken && registry.registryUrl
|
|
1297
1467
|
? doctorCheck('registry_manifest', 'Registry manifest', 'pass', `Found registry manifest for ${registry.provider || REGISTRY_PROVIDER}.`)
|
|
1298
|
-
:
|
|
1468
|
+
: redAttributionOnly
|
|
1469
|
+
? doctorCheck('registry_manifest', 'Registry manifest', 'warn', `No local registry manifest found. This does not block Red Skill safety review, but XiaShe attribution/upload reporting will be unavailable until setup runs.`, `Run ${COMMAND_NAME} setup . --code <dashboard-code> --hub red if XiaShe attribution is needed.`)
|
|
1470
|
+
: doctorCheck('registry_manifest', 'Registry manifest', 'fail', `Missing usable registry manifest (${MANIFEST_FILE} or ${WORK_DIR}/${MANIFEST_FILE}).`, `Run ${COMMAND_NAME} setup . --code <dashboard-code> or ${COMMAND_NAME} attach . --public-token <token> --skill-id <id>.`),
|
|
1299
1471
|
registryBlockPresent(skillMd)
|
|
1300
1472
|
? doctorCheck('registry_block', 'Registry block', 'pass', 'SKILL.md contains the explicit registry disclosure block.')
|
|
1301
|
-
:
|
|
1473
|
+
: redAttributionOnly
|
|
1474
|
+
? doctorCheck('registry_block', 'Registry block', 'pass', 'Full registry block is not required for Red Skill upload. Use platform fields or README only when disclosure is allowed.')
|
|
1475
|
+
: doctorCheck('registry_block', 'Registry block', 'warn', 'SKILL.md does not contain a registry block.', `Run ${COMMAND_NAME} setup . --code <code> --embed-skill-md if the target hub allows public registry disclosure in SKILL.md.`),
|
|
1302
1476
|
runtimeCallbackPresent
|
|
1303
1477
|
? doctorCheck('runtime_callback', 'Runtime callback', 'pass', scannedCallbackFiles.length > 0 ? `Runtime callback references found in ${scannedCallbackFiles.slice(0, 5).join(', ')}.` : 'Runtime callback snippet/reference detected.')
|
|
1304
|
-
:
|
|
1478
|
+
: redAttributionOnly
|
|
1479
|
+
? doctorCheck('runtime_callback', 'Runtime callback', 'pass', 'Runtime callback script is not required for Red Skill. Use Agent Ack for no-secret tracking; fall back to attribution/reported if the Agent does not call Ack.')
|
|
1480
|
+
: doctorCheck('runtime_callback', 'Runtime callback', 'warn', 'No runtime callback reference detected.', `Use ${COMMAND_NAME} snippet . --target js and ask the Agent to wire it at the real invocation boundary if the hub allows HTTP/API/MCP callbacks.`),
|
|
1305
1481
|
existsSync(disclosurePath)
|
|
1306
1482
|
? doctorCheck('disclosure', 'Read-only disclosure', 'pass', `Found ${path.relative(inspected.root, disclosurePath)}.`)
|
|
1307
1483
|
: doctorCheck('disclosure', 'Read-only disclosure', 'warn', 'REGISTRY_DISCLOSURE.md is missing.', `Run ${COMMAND_NAME} setup . --code <code> to generate platform review disclosure.`),
|
|
@@ -1357,17 +1533,21 @@ async function verifyRegistry(root, flags) {
|
|
|
1357
1533
|
const timestamp = Date.now();
|
|
1358
1534
|
const installationId = normalizeText(flags['installation-id'] || `verify-${REGISTRY_PROVIDER}-${timestamp}`, 220);
|
|
1359
1535
|
const invocationId = normalizeText(flags['invocation-id'] || `verify-call-${timestamp}`, 160);
|
|
1536
|
+
const defaultEvents = hub === 'red'
|
|
1537
|
+
? ['hub_upload_attempted']
|
|
1538
|
+
: ['runtime_install_seen', 'skill_invoked', 'skill_completed'];
|
|
1360
1539
|
const events = normalizeText(flags.events || '', 400)
|
|
1361
1540
|
? normalizeText(flags.events, 400).split(',').map((item) => normalizeText(item, 80)).filter(Boolean)
|
|
1362
|
-
:
|
|
1541
|
+
: defaultEvents;
|
|
1363
1542
|
const results = [];
|
|
1364
1543
|
for (const eventType of events) {
|
|
1544
|
+
const isRuntimeEvent = /^runtime_|^skill_/.test(eventType);
|
|
1365
1545
|
const eventResult = await submitTrackEvent(root, {
|
|
1366
1546
|
...flags,
|
|
1367
1547
|
event: eventType,
|
|
1368
1548
|
hub,
|
|
1369
|
-
'event-source': 'runtime',
|
|
1370
|
-
'runtime-kind': 'cli-verify',
|
|
1549
|
+
'event-source': isRuntimeEvent ? 'runtime' : 'cli',
|
|
1550
|
+
'runtime-kind': isRuntimeEvent ? 'cli-verify' : 'upload-check',
|
|
1371
1551
|
'source-surface': hub,
|
|
1372
1552
|
scenario,
|
|
1373
1553
|
'installation-id': installationId,
|
|
@@ -1386,11 +1566,17 @@ async function verifyRegistry(root, flags) {
|
|
|
1386
1566
|
invocationId,
|
|
1387
1567
|
registryUrl: results[0]?.registryUrl || inspected.registry?.registryUrl || DEFAULT_REGISTRY_URL,
|
|
1388
1568
|
events: results,
|
|
1389
|
-
next:
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1569
|
+
next: hub === 'red'
|
|
1570
|
+
? [
|
|
1571
|
+
'Open the creator dashboard and check upload/attribution events for Red Skill.',
|
|
1572
|
+
'Do not expect runtime health to become active from Red Skill upload alone.',
|
|
1573
|
+
'Runtime remains inactive until Red or another runtime actually calls /registry/skill-events from a real invocation boundary.'
|
|
1574
|
+
]
|
|
1575
|
+
: [
|
|
1576
|
+
'Open the creator dashboard and check 接入健康度 / Integration health.',
|
|
1577
|
+
'Verified should become active after these cli-verify events are indexed.',
|
|
1578
|
+
'If runtime remains inactive later, the third-party platform is not calling /registry/skill-events from real Skill execution.'
|
|
1579
|
+
]
|
|
1394
1580
|
};
|
|
1395
1581
|
}
|
|
1396
1582
|
|
|
@@ -1450,7 +1636,7 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
1450
1636
|
`${JSON.stringify(Object.fromEntries(hubs.map((hub) => [hub, reviewProfileForHub(hub)])), null, 2)}\n`,
|
|
1451
1637
|
{ mode: 0o600 }
|
|
1452
1638
|
);
|
|
1453
|
-
const shouldEmbedSkillMd = Boolean(flags['embed-skill-md'])
|
|
1639
|
+
const shouldEmbedSkillMd = Boolean(flags['embed-skill-md']) && !flags['no-skill-md'];
|
|
1454
1640
|
const skillMdPath = shouldEmbedSkillMd
|
|
1455
1641
|
? await writeSkillMdRegistryBlock(absoluteRoot, inspectedAfterManifest, hubs.join(','))
|
|
1456
1642
|
: null;
|
|
@@ -1462,6 +1648,8 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
1462
1648
|
.join('\n')}\n`,
|
|
1463
1649
|
{ mode: 0o600 }
|
|
1464
1650
|
);
|
|
1651
|
+
const agentAckPath = path.join(outDir, 'AGENT_ACK.md');
|
|
1652
|
+
await writeFile(agentAckPath, `${agentAckInstructionBlock(inspectedAfterManifest, hubs.join(','))}\n`, { mode: 0o600 });
|
|
1465
1653
|
const snippetPath = path.join(outDir, 'runtime-events.js');
|
|
1466
1654
|
let snippetResult = null;
|
|
1467
1655
|
if (!flags['no-snippet']) {
|
|
@@ -1509,6 +1697,7 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
1509
1697
|
packagePlanPaths: packagePlans.map((item) => ({ hub: item.hub, planPath: item.planPath })),
|
|
1510
1698
|
profilesPath,
|
|
1511
1699
|
skillMdPath,
|
|
1700
|
+
agentAckPath,
|
|
1512
1701
|
disclosurePath,
|
|
1513
1702
|
snippetPath: snippetResult ? snippetResult.outPath : null,
|
|
1514
1703
|
promptEvents,
|
|
@@ -1516,11 +1705,12 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
1516
1705
|
next: [
|
|
1517
1706
|
`Use ${path.relative(absoluteRoot, handoffPath)} as the single Agent handoff. The Agent should not ask the user to manually pick registry files.`,
|
|
1518
1707
|
`Use ${path.relative(absoluteRoot, profilesPath)} and package-<hub>.json as the platform review profiles and upload allowlists.`,
|
|
1519
|
-
|
|
1708
|
+
`Use ${path.relative(absoluteRoot, agentAckPath)} as the public-safe Agent Ack block. Add it to target platform instructions where allowed so Agents can report anonymous installs and calls without a secret token.`,
|
|
1709
|
+
'When the user later pastes a Red Skill / ClawHub / SkillHub / Claude / Dify / Coze official prompt, the Agent should identify the platform and merge only the matching platform-safe checklist internally.',
|
|
1520
1710
|
'Each prepared upload-<hub>.md pins the correct hub/sourceSurface value so platform analytics stay separated, but those files are internal checklists for the Agent.',
|
|
1521
1711
|
skillMdPath
|
|
1522
1712
|
? `Registry disclosure was also embedded into ${path.relative(absoluteRoot, skillMdPath)} for restrictive hubs.`
|
|
1523
|
-
: `If
|
|
1713
|
+
: `If a hub explicitly allows disclosure in SKILL.md and the user wants it, rerun with --embed-skill-md. For Red Skill, prefer platform fields/README and keep registry runtime details local.`,
|
|
1524
1714
|
`Use ${path.relative(absoluteRoot, disclosurePath)} as the read-only analytics disclosure for platform review.`,
|
|
1525
1715
|
'Do not upload secrets, .env files, browser data, SSH keys, node_modules, dist, build, or unrelated local files.',
|
|
1526
1716
|
`If the Skill is published, record the public URL with: ${COMMAND_NAME} track . --event hub_upload_succeeded --hub <red|clawhub|skillhub|claude|dify|coze|generic> --platform-skill-url <url>`,
|
|
@@ -1585,7 +1775,10 @@ async function main() {
|
|
|
1585
1775
|
'Next:',
|
|
1586
1776
|
'- Treat the target platform official upload flow as authoritative.',
|
|
1587
1777
|
'- Use the handoff file as the only XiaShe registry checklist.',
|
|
1588
|
-
'-
|
|
1778
|
+
'- Before uploading, check whether this Skill already has a draft, submitted review, or published listing for the selected target; skip duplicate uploads and verify/update the existing record when possible.',
|
|
1779
|
+
'- Check upload readiness and runtime readiness separately before submission.',
|
|
1780
|
+
'- For XiaShe Store, create or update the store draft only when an authenticated creator CLI/API session is available.',
|
|
1781
|
+
'- If no authenticated creator session is available, finish registry setup and handoff files without asking the Agent host for account credentials.',
|
|
1589
1782
|
'- For Markdown/TXT-only platforms, copy the disclosure text into an allowed public field instead of uploading registry JSON.',
|
|
1590
1783
|
'- Only count runtime usage when the Skill or Agent callback sends real runtime events.'
|
|
1591
1784
|
].filter(Boolean);
|