@xiashe/skill 0.1.21 → 0.1.22
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/bin/xiashe-skill.mjs +151 -31
- package/package.json +1 -1
package/bin/xiashe-skill.mjs
CHANGED
|
@@ -1,19 +1,97 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { createHash, createHmac } from 'node:crypto';
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
4
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
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
|
+
import { fileURLToPath } from 'node:url';
|
|
8
9
|
import { promisify } from 'node:util';
|
|
9
10
|
import { gzip } from 'node:zlib';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
function parseEnvFile(filePath) {
|
|
13
|
+
if (!existsSync(filePath)) return {};
|
|
14
|
+
const parsed = {};
|
|
15
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
16
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
17
|
+
const trimmed = line.trim();
|
|
18
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
19
|
+
const match = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
20
|
+
if (!match) continue;
|
|
21
|
+
let value = match[2].trim();
|
|
22
|
+
if (
|
|
23
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
24
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
25
|
+
) {
|
|
26
|
+
value = value.slice(1, -1);
|
|
27
|
+
}
|
|
28
|
+
parsed[match[1]] = value;
|
|
29
|
+
}
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function nearestEnvFiles() {
|
|
34
|
+
const files = [];
|
|
35
|
+
let cursor = process.cwd();
|
|
36
|
+
for (let index = 0; index < 8; index += 1) {
|
|
37
|
+
files.push(path.join(cursor, '.env.local'));
|
|
38
|
+
files.push(path.join(cursor, 'convex', '.env.local'));
|
|
39
|
+
const next = path.dirname(cursor);
|
|
40
|
+
if (next === cursor) break;
|
|
41
|
+
cursor = next;
|
|
42
|
+
}
|
|
43
|
+
return files;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function loadLocalEnvDefaults() {
|
|
47
|
+
const cliDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
|
48
|
+
const candidates = [
|
|
49
|
+
path.join(cliDir, '.env.local'),
|
|
50
|
+
path.join(cliDir, 'convex', '.env.local'),
|
|
51
|
+
...nearestEnvFiles()
|
|
52
|
+
];
|
|
53
|
+
const env = {};
|
|
54
|
+
for (const filePath of candidates) {
|
|
55
|
+
Object.assign(env, parseEnvFile(filePath));
|
|
56
|
+
}
|
|
57
|
+
return env;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeBaseUrl(value) {
|
|
61
|
+
const text = String(value || '').trim().replace(/\/+$/, '');
|
|
62
|
+
return /^https?:\/\//i.test(text) ? text : '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isTransportError(error) {
|
|
66
|
+
const message = error instanceof Error ? `${error.name || ''} ${error.message || ''}` : String(error || '');
|
|
67
|
+
return /abort|timeout|fetch failed|network|enotfound|eai_again|econnrefused|econnreset|etimedout|unable to verify|certificate/i.test(message);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const LOCAL_ENV_DEFAULTS = loadLocalEnvDefaults();
|
|
71
|
+
const VERSION = process.env.XIASHE_SKILL_CLI_VERSION || '0.1.22';
|
|
12
72
|
const COMMAND_NAME = process.env.XIASHE_SKILL_CLI_NAME || 'xiashe-skill';
|
|
13
73
|
const PRODUCT_NAME = process.env.XIASHE_SKILL_PRODUCT_NAME || (COMMAND_NAME === 'agentpie-skill' ? 'AgentPie' : 'XiaShe');
|
|
14
74
|
const REGISTRY_PROVIDER = process.env.XIASHE_SKILL_REGISTRY_PROVIDER || (COMMAND_NAME === 'agentpie-skill' ? 'agentpie' : 'xiashe');
|
|
75
|
+
const LOCAL_AGENTPIE_BASE_URL = normalizeBaseUrl(
|
|
76
|
+
process.env.AGENTPIE_SKILL_DEFAULT_BASE_URL ||
|
|
77
|
+
LOCAL_ENV_DEFAULTS.AGENTPIE_SKILL_DEFAULT_BASE_URL ||
|
|
78
|
+
process.env.AGENTPIE_SKILL_REGISTRY_PUBLIC_URL ||
|
|
79
|
+
LOCAL_ENV_DEFAULTS.AGENTPIE_SKILL_REGISTRY_PUBLIC_URL ||
|
|
80
|
+
process.env.AGENTPIE_ACTIONS_URL ||
|
|
81
|
+
LOCAL_ENV_DEFAULTS.AGENTPIE_ACTIONS_URL ||
|
|
82
|
+
process.env.CREATOR_SKILL_REGISTRY_PUBLIC_URL ||
|
|
83
|
+
LOCAL_ENV_DEFAULTS.CREATOR_SKILL_REGISTRY_PUBLIC_URL ||
|
|
84
|
+
process.env.AGENTPIE_MCP_PUBLIC_URL ||
|
|
85
|
+
LOCAL_ENV_DEFAULTS.AGENTPIE_MCP_PUBLIC_URL ||
|
|
86
|
+
process.env.PUBLIC_CONVEX_SITE_URL ||
|
|
87
|
+
LOCAL_ENV_DEFAULTS.PUBLIC_CONVEX_SITE_URL ||
|
|
88
|
+
process.env.CONVEX_SITE_URL ||
|
|
89
|
+
LOCAL_ENV_DEFAULTS.CONVEX_SITE_URL ||
|
|
90
|
+
process.env.EXPO_PUBLIC_CONVEX_SITE_URL ||
|
|
91
|
+
LOCAL_ENV_DEFAULTS.EXPO_PUBLIC_CONVEX_SITE_URL
|
|
92
|
+
);
|
|
15
93
|
const DEFAULT_BASE_URL = process.env.XIASHE_SKILL_DEFAULT_BASE_URL || (COMMAND_NAME === 'agentpie-skill'
|
|
16
|
-
? 'https://
|
|
94
|
+
? LOCAL_AGENTPIE_BASE_URL || 'https://agentpie.app'
|
|
17
95
|
: 'https://actions.xiashe.chat');
|
|
18
96
|
const MANIFEST_FILE = process.env.XIASHE_SKILL_MANIFEST_FILE || (COMMAND_NAME === 'agentpie-skill'
|
|
19
97
|
? 'agentpie.skill.json'
|
|
@@ -32,10 +110,11 @@ const EVENT_SCHEMA_VERSION = process.env.XIASHE_SKILL_EVENT_SCHEMA_VERSION || (R
|
|
|
32
110
|
const RUNTIME_SCHEMA_VERSION = process.env.XIASHE_SKILL_RUNTIME_SCHEMA_VERSION || (REGISTRY_PROVIDER === 'agentpie'
|
|
33
111
|
? 'agentpie.skill.runtime.v1'
|
|
34
112
|
: 'xiashe.skill.runtime.v1');
|
|
35
|
-
const
|
|
36
|
-
const
|
|
113
|
+
const FIRST_PARTY_HUB = REGISTRY_PROVIDER === 'agentpie' ? 'agentpie' : 'xiashe';
|
|
114
|
+
const SUPPORTED_HUBS = ['agentpie', 'xiashe', 'red', 'clawhub', 'skillhub', 'claude', 'codex', 'cursor', 'workbuddy', 'dify', 'coze', 'generic'];
|
|
115
|
+
const DEFAULT_SETUP_HUBS = [FIRST_PARTY_HUB, 'red'];
|
|
37
116
|
const ACK_EVENTS = ['installed', 'used', 'completed', 'failed'];
|
|
38
|
-
const RUNTIME_DISTRIBUTION_PLATFORMS = ['xiaohongshu-redskill', 'xiashe', 'coze-store', 'local', 'unknown'];
|
|
117
|
+
const RUNTIME_DISTRIBUTION_PLATFORMS = ['xiaohongshu-redskill', 'agentpie', 'xiashe', 'coze-store', 'local', 'unknown'];
|
|
39
118
|
const RUNTIME_AGENTS = ['codex', 'workbuddy', 'coze', 'claude', 'cursor', 'dify', 'custom-agent', 'unknown'];
|
|
40
119
|
const RUNTIME_HOSTS = ['codex-desktop', 'coze-app', 'web-chat', 'desktop', 'web', 'server', 'mobile', 'unknown'];
|
|
41
120
|
const RUNTIME_SOURCE_SURFACES = ['install', 'first-use-backfill', 'chat-use', 'manual-test', 'creator-card', 'dashboard', 'unknown'];
|
|
@@ -79,6 +158,16 @@ const FORBIDDEN_ACK_FIELDS = [
|
|
|
79
158
|
'privateResearchMaterial'
|
|
80
159
|
];
|
|
81
160
|
const PLATFORM_REVIEW_PROFILES = {
|
|
161
|
+
agentpie: {
|
|
162
|
+
label: 'AgentPie Registry',
|
|
163
|
+
packageMode: 'full_skill_package',
|
|
164
|
+
manifestPolicy: 'upload_allowed',
|
|
165
|
+
disclosurePlacement: ['Skill public page', 'README', `${WORK_DIR}/REGISTRY_DISCLOSURE.md`],
|
|
166
|
+
runtimeDataPolicy: 'runtime_capable',
|
|
167
|
+
defaultDataSource: 'runtime',
|
|
168
|
+
allowedFilePolicy: 'Upload the complete reviewed Skill package, including the local registry manifest.',
|
|
169
|
+
forbiddenPublicFiles: ['.env', 'credentials', 'node_modules', 'dist', 'build', 'browser profiles', 'SSH keys']
|
|
170
|
+
},
|
|
82
171
|
xiashe: {
|
|
83
172
|
label: 'XiaShe Store',
|
|
84
173
|
packageMode: 'full_skill_package',
|
|
@@ -224,14 +313,14 @@ function usage() {
|
|
|
224
313
|
|
|
225
314
|
Usage:
|
|
226
315
|
${COMMAND_NAME} inspect [skill-dir] [--json]
|
|
227
|
-
${COMMAND_NAME} publish [skill-dir] --code <dynamic-code> [--to
|
|
228
|
-
${COMMAND_NAME} setup [skill-dir] --code <dynamic-code> [--hub all|
|
|
229
|
-
${COMMAND_NAME} setup [skill-dir] --public-token <token> --skill-id <id> [--hub all|
|
|
316
|
+
${COMMAND_NAME} publish [skill-dir] --code <dynamic-code> [--to ${FIRST_PARTY_HUB},red]
|
|
317
|
+
${COMMAND_NAME} setup [skill-dir] --code <dynamic-code> [--hub all|${FIRST_PARTY_HUB}|red]
|
|
318
|
+
${COMMAND_NAME} setup [skill-dir] --public-token <token> --skill-id <id> [--hub all|${FIRST_PARTY_HUB}|red]
|
|
230
319
|
${COMMAND_NAME} doctor [skill-dir] [--json]
|
|
231
320
|
${COMMAND_NAME} verify [skill-dir] [--hub <hub>] [--scenario <label>] [--dry-run]
|
|
232
321
|
${COMMAND_NAME} attach [skill-dir] --code <dynamic-code> [--name <name>]
|
|
233
322
|
${COMMAND_NAME} attach [skill-dir] --public-token <token> [--skill-id <id>] [--name <name>]
|
|
234
|
-
${COMMAND_NAME} prompt [skill-dir] --hub
|
|
323
|
+
${COMMAND_NAME} prompt [skill-dir] --hub <${FIRST_PARTY_HUB}|red> [--source-url <url>] [--out <file>]
|
|
235
324
|
${COMMAND_NAME} snippet [skill-dir] [--target js|curl] [--out <file>]
|
|
236
325
|
${COMMAND_NAME} track [skill-dir] --event <event> [--hub <hub>] [--installation-id <id>] [--invocation-id <id>]
|
|
237
326
|
|
|
@@ -244,7 +333,7 @@ Options:
|
|
|
244
333
|
--agent-ack-url <url> No-secret Agent Ack endpoint written to the local manifest.
|
|
245
334
|
--name <name> Skill display name override.
|
|
246
335
|
--description <text> Skill description override.
|
|
247
|
-
--hub <hub> Target Skill hub prompt style. setup defaults to
|
|
336
|
+
--hub <hub> Target Skill hub prompt style. setup defaults to ${DEFAULT_SETUP_HUBS.join(',')}.
|
|
248
337
|
--to <hub[,hub]> High-level publish targets. Alias for --hub in publish mode.
|
|
249
338
|
--event <event> Runtime event to submit for testing.
|
|
250
339
|
--installation-id <id> Stable anonymous install id for runtime analytics.
|
|
@@ -271,7 +360,7 @@ Options:
|
|
|
271
360
|
--package-artifact-url <url> Package artifact attach endpoint. Defaults to ${DEFAULT_PACKAGE_ARTIFACT_URL}
|
|
272
361
|
--out <path> Output prompt or snippet file.
|
|
273
362
|
--out-dir <path> Output directory for setup artifacts. Defaults to ${WORK_DIR}/.
|
|
274
|
-
--no-
|
|
363
|
+
--no-package-upload Skip automatic ${PRODUCT_NAME} complete package upload.
|
|
275
364
|
--embed-skill-md Also write a clearly marked registry section into SKILL.md.
|
|
276
365
|
--no-skill-md Do not write registry text into SKILL.md. Red hub embeds by default.
|
|
277
366
|
--no-snippet Setup should skip writing the runtime analytics snippet.
|
|
@@ -290,7 +379,7 @@ function fail(message, code = 1) {
|
|
|
290
379
|
|
|
291
380
|
function parseArgs(argv) {
|
|
292
381
|
const args = { _: [], json: false, dryRun: false };
|
|
293
|
-
const booleanFlags = new Set(['embed-skill-md', 'no-skill-md', 'no-snippet', 'no-track', 'no-xiashe-package-upload']);
|
|
382
|
+
const booleanFlags = new Set(['embed-skill-md', 'no-skill-md', 'no-snippet', 'no-track', 'no-package-upload', 'no-xiashe-package-upload']);
|
|
294
383
|
for (let i = 0; i < argv.length; i += 1) {
|
|
295
384
|
const value = argv[i];
|
|
296
385
|
if (value === '--help' || value === '-h') {
|
|
@@ -487,6 +576,9 @@ function normalizeHub(value) {
|
|
|
487
576
|
if (hub === 'xiashechat' || hub === 'xia-she' || hub === 'xiashe-store') {
|
|
488
577
|
return 'xiashe';
|
|
489
578
|
}
|
|
579
|
+
if (hub === 'agent-pie' || hub === 'agentpieapp' || hub === 'agentpie-registry' || hub === 'agentpieregistry') {
|
|
580
|
+
return 'agentpie';
|
|
581
|
+
}
|
|
490
582
|
if (hub === 'claudecode' || hub === 'claude-code') {
|
|
491
583
|
return 'claude';
|
|
492
584
|
}
|
|
@@ -742,6 +834,12 @@ async function postJson(url, body, timeoutMs = 20_000) {
|
|
|
742
834
|
throw new Error(payload.error || payload.message || `HTTP ${response.status}`);
|
|
743
835
|
}
|
|
744
836
|
return payload;
|
|
837
|
+
} catch (error) {
|
|
838
|
+
const message = error instanceof Error ? error.message : String(error || 'unknown error');
|
|
839
|
+
if (!isTransportError(error)) {
|
|
840
|
+
throw error;
|
|
841
|
+
}
|
|
842
|
+
throw new Error(`Network request failed for ${url}: ${message}`);
|
|
745
843
|
} finally {
|
|
746
844
|
clearTimeout(timer);
|
|
747
845
|
}
|
|
@@ -896,10 +994,10 @@ async function buildXiashePackageArtifact(root, inspected, flags = {}) {
|
|
|
896
994
|
const skillMarkdownPresent = files.some((file) => /^SKILL(\.[a-z0-9]+)?$/i.test(file.relative));
|
|
897
995
|
const manifestPresent = files.some((file) => file.relative === manifestRelative);
|
|
898
996
|
if (!skillMarkdownPresent) {
|
|
899
|
-
throw new Error(
|
|
997
|
+
throw new Error(`SKILL.md is required before uploading the ${PRODUCT_NAME} complete package.`);
|
|
900
998
|
}
|
|
901
999
|
if (!manifestPresent) {
|
|
902
|
-
throw new Error(`${manifestRelative} is required before uploading the
|
|
1000
|
+
throw new Error(`${manifestRelative} is required before uploading the ${PRODUCT_NAME} complete package.`);
|
|
903
1001
|
}
|
|
904
1002
|
const artifact = await createTarGz(files);
|
|
905
1003
|
const artifactDir = path.resolve(flags['package-out-dir'] || path.join(absoluteRoot, WORK_DIR, 'package-artifact'));
|
|
@@ -947,13 +1045,19 @@ async function uploadBytesToStorage(uploadUrl, bytes, contentType, timeoutMs = 6
|
|
|
947
1045
|
throw new Error('Upload response did not include storageId.');
|
|
948
1046
|
}
|
|
949
1047
|
return { ...payload, storageId };
|
|
1048
|
+
} catch (error) {
|
|
1049
|
+
const message = error instanceof Error ? error.message : String(error || 'unknown error');
|
|
1050
|
+
if (!isTransportError(error)) {
|
|
1051
|
+
throw error;
|
|
1052
|
+
}
|
|
1053
|
+
throw new Error(`Package upload failed for ${uploadUrl}: ${message}`);
|
|
950
1054
|
} finally {
|
|
951
1055
|
clearTimeout(timer);
|
|
952
1056
|
}
|
|
953
1057
|
}
|
|
954
1058
|
|
|
955
1059
|
async function uploadXiashePackageArtifact(root, flags, manifestResult) {
|
|
956
|
-
if (flags.dryRun || flags['no-xiashe-package-upload']) {
|
|
1060
|
+
if (flags.dryRun || flags['no-package-upload'] || flags['no-xiashe-package-upload']) {
|
|
957
1061
|
return {
|
|
958
1062
|
ok: true,
|
|
959
1063
|
skipped: true,
|
|
@@ -964,7 +1068,7 @@ async function uploadXiashePackageArtifact(root, flags, manifestResult) {
|
|
|
964
1068
|
const registry = manifestResult.manifest?.registry || inspected.registry || {};
|
|
965
1069
|
const publicToken = normalizeText(registry.publicToken, 512);
|
|
966
1070
|
if (!publicToken) {
|
|
967
|
-
throw new Error(
|
|
1071
|
+
throw new Error(`Cannot upload ${PRODUCT_NAME} package without registry publicToken.`);
|
|
968
1072
|
}
|
|
969
1073
|
const artifact = await buildXiashePackageArtifact(root, inspected, flags);
|
|
970
1074
|
const registrySourceSha256 =
|
|
@@ -1004,7 +1108,7 @@ async function uploadXiashePackageArtifact(root, flags, manifestResult) {
|
|
|
1004
1108
|
manifestPresent: artifact.manifestPresent,
|
|
1005
1109
|
skillMarkdownPresent: artifact.skillMarkdownPresent,
|
|
1006
1110
|
creatorCardUrl: normalizeText(registry.creatorCardUrl, 800) || undefined,
|
|
1007
|
-
platformSource:
|
|
1111
|
+
platformSource: REGISTRY_PROVIDER,
|
|
1008
1112
|
source: `${REGISTRY_PROVIDER}_skill_cli`
|
|
1009
1113
|
},
|
|
1010
1114
|
Number(flags['timeout-ms'] || 20_000)
|
|
@@ -1183,6 +1287,9 @@ async function writeManifest(root, flags) {
|
|
|
1183
1287
|
}
|
|
1184
1288
|
|
|
1185
1289
|
function hubInstruction(hub) {
|
|
1290
|
+
if (hub === 'agentpie') {
|
|
1291
|
+
return 'AgentPie Registry publish is the full Skill package and registry manifest flow. Keep public disclosure, attribution, and runtime analytics callbacks; if the local manifest has a registry public token or a creator-authenticated CLI/API session exists, create or reuse the AgentPie registry draft.';
|
|
1292
|
+
}
|
|
1186
1293
|
if (hub === 'xiashe') {
|
|
1187
1294
|
return '虾舍商店发布是完整 Skill 包和 registry manifest 的主流程。请保留公开披露、归因和 runtime analytics 回传能力;如果本地 manifest 有 registry public token 或已有创作者认证 CLI/API 会话,就创建或复用虾舍商店草稿。';
|
|
1188
1295
|
}
|
|
@@ -1217,6 +1324,9 @@ function hubInstruction(hub) {
|
|
|
1217
1324
|
}
|
|
1218
1325
|
|
|
1219
1326
|
function platformPromptPlaceholder(hub) {
|
|
1327
|
+
if (hub === 'agentpie') {
|
|
1328
|
+
return 'If the user is publishing to AgentPie Registry and the current environment has a creator-authenticated CLI/API session, create the AgentPie registry draft first; otherwise finish registry setup, disclosure, platform profile, and handoff files. Do not apply third-party marketplace limits to the AgentPie complete Skill package.';
|
|
1329
|
+
}
|
|
1220
1330
|
if (hub === 'xiashe') {
|
|
1221
1331
|
return '如果用户要发布到虾舍商店,并且当前环境已有创作者认证 CLI/API 会话,请优先创建虾舍商店草稿;如果没有认证会话,请完成 registry setup、披露、平台 profile 和 handoff 文件,不要要求 Agent 宿主登录或索取账号凭证。不要把第三方平台限制套用到虾舍完整 Skill 包。';
|
|
1222
1332
|
}
|
|
@@ -1252,6 +1362,14 @@ function platformPromptPlaceholder(hub) {
|
|
|
1252
1362
|
|
|
1253
1363
|
function uploadCompatibilityLines(hub, manifestFile) {
|
|
1254
1364
|
const localManifest = `${WORK_DIR}/${manifestFile}`;
|
|
1365
|
+
if (hub === 'agentpie') {
|
|
1366
|
+
return [
|
|
1367
|
+
'AgentPie Registry compatibility requirements:',
|
|
1368
|
+
`- AgentPie Registry can receive the complete Skill package and ${localManifest} registry manifest.`,
|
|
1369
|
+
'- Keep public disclosure text, attribution links, and runtime event callbacks; do not remove the registry manifest.',
|
|
1370
|
+
'- Before submitting a draft, still exclude .env, keys, node_modules, dist/build, and unrelated local files.'
|
|
1371
|
+
];
|
|
1372
|
+
}
|
|
1255
1373
|
if (hub === 'xiashe') {
|
|
1256
1374
|
return [
|
|
1257
1375
|
'虾舍商店兼容性要求:',
|
|
@@ -1542,6 +1660,7 @@ function yamlStringList(values, indent = 6) {
|
|
|
1542
1660
|
function runtimeDistributionPlatformForHub(hub) {
|
|
1543
1661
|
const normalized = normalizeHub(hub) || 'unknown';
|
|
1544
1662
|
if (normalized === 'red') return 'xiaohongshu-redskill';
|
|
1663
|
+
if (normalized === 'agentpie') return 'agentpie';
|
|
1545
1664
|
if (normalized === 'xiashe') return 'xiashe';
|
|
1546
1665
|
if (normalized === 'coze') return 'coze-store';
|
|
1547
1666
|
if (normalized === 'codex' || normalized === 'claude' || normalized === 'cursor' || normalized === 'workbuddy') return 'local';
|
|
@@ -2650,12 +2769,13 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
2650
2769
|
promptResults,
|
|
2651
2770
|
packagePlans
|
|
2652
2771
|
});
|
|
2653
|
-
const
|
|
2772
|
+
const firstPartyPackageHubSelected = hubs.includes(FIRST_PARTY_HUB);
|
|
2773
|
+
const firstPartyPackageArtifact = firstPartyPackageHubSelected && (REGISTRY_PROVIDER === 'xiashe' || REGISTRY_PROVIDER === 'agentpie')
|
|
2654
2774
|
? await uploadXiashePackageArtifact(absoluteRoot, flags, manifestResult)
|
|
2655
2775
|
: {
|
|
2656
2776
|
ok: true,
|
|
2657
2777
|
skipped: true,
|
|
2658
|
-
reason:
|
|
2778
|
+
reason: firstPartyPackageHubSelected ? 'unsupported_registry_provider' : 'first_party_registry_not_selected'
|
|
2659
2779
|
};
|
|
2660
2780
|
|
|
2661
2781
|
const warnings = [];
|
|
@@ -2691,14 +2811,14 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
2691
2811
|
agentAckPath,
|
|
2692
2812
|
disclosurePath,
|
|
2693
2813
|
snippetPath: snippetResult ? snippetResult.outPath : null,
|
|
2694
|
-
|
|
2814
|
+
firstPartyPackageArtifact,
|
|
2695
2815
|
promptEvents,
|
|
2696
2816
|
warnings,
|
|
2697
2817
|
publicProtocol,
|
|
2698
2818
|
next: [
|
|
2699
|
-
|
|
2700
|
-
?
|
|
2701
|
-
:
|
|
2819
|
+
firstPartyPackageArtifact?.skipped
|
|
2820
|
+
? `${PRODUCT_NAME} complete package upload was skipped (${firstPartyPackageArtifact.reason}).`
|
|
2821
|
+
: `${PRODUCT_NAME} complete package uploaded: ${path.relative(absoluteRoot, firstPartyPackageArtifact.artifactPath)} (${firstPartyPackageArtifact.publishStatus || 'queued'}).`,
|
|
2702
2822
|
`Use ${path.relative(absoluteRoot, handoffPath)} as the single Agent handoff. The Agent should not ask the user to manually pick registry files.`,
|
|
2703
2823
|
`Use ${path.relative(absoluteRoot, profilesPath)} and package-<hub>.json as the platform review profiles and upload allowlists.`,
|
|
2704
2824
|
publicProtocol
|
|
@@ -2756,7 +2876,7 @@ async function main() {
|
|
|
2756
2876
|
if (command === 'publish') {
|
|
2757
2877
|
const result = await setupAgentWorkflow(root, flags);
|
|
2758
2878
|
if (flags.json) {
|
|
2759
|
-
print({ ok: true, mode:
|
|
2879
|
+
print({ ok: true, mode: `${REGISTRY_PROVIDER}-publish`, ...result }, true);
|
|
2760
2880
|
} else {
|
|
2761
2881
|
const lines = [
|
|
2762
2882
|
`${PRODUCT_NAME} publish handoff prepared.`,
|
|
@@ -2767,8 +2887,8 @@ async function main() {
|
|
|
2767
2887
|
...result.packagePlanPaths.map((item) => `Package plan (${item.hub}): ${item.planPath}`),
|
|
2768
2888
|
result.skillMdPath ? `Updated: ${result.skillMdPath}` : null,
|
|
2769
2889
|
result.publicProtocol ? `Public Red protocol: ${result.publicProtocol.runtimePath}, ${result.publicProtocol.agentAckPath}, ${result.publicProtocol.disclosurePath}` : null,
|
|
2770
|
-
result.
|
|
2771
|
-
?
|
|
2890
|
+
result.firstPartyPackageArtifact && !result.firstPartyPackageArtifact.skipped
|
|
2891
|
+
? `${PRODUCT_NAME} package: ${result.firstPartyPackageArtifact.artifactPath} (${result.firstPartyPackageArtifact.publishStatus || 'queued'})`
|
|
2772
2892
|
: null,
|
|
2773
2893
|
`Disclosure: ${result.disclosurePath}`,
|
|
2774
2894
|
result.snippetPath ? `Runtime snippet: ${result.snippetPath}` : null,
|
|
@@ -2776,8 +2896,8 @@ async function main() {
|
|
|
2776
2896
|
'',
|
|
2777
2897
|
'Next:',
|
|
2778
2898
|
'- Treat the target platform official upload flow as authoritative.',
|
|
2779
|
-
|
|
2780
|
-
|
|
2899
|
+
`- Use the handoff file as the only ${PRODUCT_NAME} registry checklist.`,
|
|
2900
|
+
`- ${PRODUCT_NAME} complete package upload is already handled by this command when the first-party registry target is selected.`,
|
|
2781
2901
|
'- Before uploading to third-party targets, 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.',
|
|
2782
2902
|
'- Check upload readiness and runtime readiness separately before submission.',
|
|
2783
2903
|
'- Only ask for creator CLI login if a separate store-management command is needed and the registry public token is missing or rejected.',
|
|
@@ -2802,8 +2922,8 @@ async function main() {
|
|
|
2802
2922
|
result.publicProtocol ? `Wrote ${result.publicProtocol.runtimePath}` : null,
|
|
2803
2923
|
result.publicProtocol ? `Wrote ${result.publicProtocol.agentAckPath}` : null,
|
|
2804
2924
|
result.publicProtocol ? `Wrote ${result.publicProtocol.disclosurePath}` : null,
|
|
2805
|
-
result.
|
|
2806
|
-
? `Uploaded
|
|
2925
|
+
result.firstPartyPackageArtifact && !result.firstPartyPackageArtifact.skipped
|
|
2926
|
+
? `Uploaded ${PRODUCT_NAME} package ${result.firstPartyPackageArtifact.artifactPath} (${result.firstPartyPackageArtifact.publishStatus || 'queued'})`
|
|
2807
2927
|
: null,
|
|
2808
2928
|
`Wrote ${result.disclosurePath}`,
|
|
2809
2929
|
result.snippetPath ? `Wrote ${result.snippetPath}` : null,
|