@xiashe/skill 0.1.23 → 0.1.24

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 CHANGED
@@ -51,8 +51,9 @@ Use the `claimUrl` returned with a dashboard dynamic code exactly as issued. `pu
51
51
  The publish path keeps three different values separate:
52
52
 
53
53
  - **Source fingerprint** — a stable SHA-256 of reviewed Skill source files. It is the idempotency key for the publish job.
54
- - **Artifact checksum** — SHA-256 of the generated `.tgz` bytes. The backend compares it only with storage's checksum for those exact bytes.
55
- - **Storage checksum** — the checksum reported after upload. It must match the artifact checksum; it is never compared with the source fingerprint.
54
+ - **Artifact checksum** — SHA-256 of the generated `.tgz` bytes, sent with the upload request.
55
+ - **Storage metadata checksum** — an upload-store diagnostic; it is never trusted as the sole proof of the uploaded bytes.
56
+ - **Verified upload checksum** — the backend rehashes the exact stored archive bytes and compares that value with the artifact checksum. None of these are compared with the source fingerprint.
56
57
 
57
58
  If the network breaks after the server receives a dynamic-code claim, rerun the exact same `publish` command before that code expires. The registry accepts only the same code and source fingerprint, returns the original local manifest credentials, and reuses the same package job. It never creates a second Skill or a second upload job. Do not generate a new dashboard code merely because a local HTTP response was interrupted.
58
59
 
@@ -68,7 +68,7 @@ function isTransportError(error) {
68
68
  }
69
69
 
70
70
  const LOCAL_ENV_DEFAULTS = loadLocalEnvDefaults();
71
- const VERSION = process.env.XIASHE_SKILL_CLI_VERSION || '0.1.23';
71
+ const VERSION = process.env.XIASHE_SKILL_CLI_VERSION || '0.1.24';
72
72
  const COMMAND_NAME = process.env.XIASHE_SKILL_CLI_NAME || 'xiashe-skill';
73
73
  const PRODUCT_NAME = process.env.XIASHE_SKILL_PRODUCT_NAME || (COMMAND_NAME === 'agentpie-skill' ? 'AgentPie' : 'XiaShe');
74
74
  const REGISTRY_PROVIDER = process.env.XIASHE_SKILL_REGISTRY_PROVIDER || (COMMAND_NAME === 'agentpie-skill' ? 'agentpie' : 'xiashe');
@@ -98,6 +98,7 @@ const MANIFEST_FILE = process.env.XIASHE_SKILL_MANIFEST_FILE || (COMMAND_NAME ==
98
98
  : 'xiashe.skill.json');
99
99
  const WORK_DIR = process.env.XIASHE_SKILL_WORK_DIR || (COMMAND_NAME === 'agentpie-skill' ? '.agentpie' : '.xiashe');
100
100
  const PUBLIC_PROTOCOL_DIR = process.env.XIASHE_SKILL_PUBLIC_PROTOCOL_DIR || (REGISTRY_PROVIDER === 'agentpie' ? 'agentpie' : 'xiashe');
101
+ const PUBLIC_PACKAGE_MANIFEST_FILE = 'package-manifest.json';
101
102
  const HANDOFF_FILE = 'UPLOAD_HANDOFF.md';
102
103
  const DEFAULT_REGISTRY_URL = process.env.XIASHE_SKILL_REGISTRY_URL || `${DEFAULT_BASE_URL}/registry/skill-events`;
103
104
  const DEFAULT_AGENT_ACK_URL = process.env.XIASHE_SKILL_AGENT_ACK_URL || `${DEFAULT_BASE_URL}/registry/agent-ack`;
@@ -163,8 +164,8 @@ const PLATFORM_REVIEW_PROFILES = {
163
164
  disclosurePlacement: ['Skill public page', 'README', `${WORK_DIR}/REGISTRY_DISCLOSURE.md`],
164
165
  runtimeDataPolicy: 'runtime_capable',
165
166
  defaultDataSource: 'runtime',
166
- allowedFilePolicy: 'Upload the complete reviewed Skill package, including the local registry manifest.',
167
- forbiddenPublicFiles: ['.env', 'credentials', 'node_modules', 'dist', 'build', 'browser profiles', 'SSH keys']
167
+ allowedFilePolicy: 'Upload the complete reviewed Skill package together with the generated no-secret package manifest. Keep the local registry manifest and runtime credentials on the creator device.',
168
+ forbiddenPublicFiles: [WORK_DIR, '.env', 'credentials', 'node_modules', 'dist', 'build', 'browser profiles', 'SSH keys', 'public tokens', 'signing secrets']
168
169
  },
169
170
  xiashe: {
170
171
  label: 'XiaShe Store',
@@ -173,8 +174,8 @@ const PLATFORM_REVIEW_PROFILES = {
173
174
  disclosurePlacement: ['Skill public page', 'README', `${WORK_DIR}/REGISTRY_DISCLOSURE.md`],
174
175
  runtimeDataPolicy: 'runtime_capable',
175
176
  defaultDataSource: 'runtime',
176
- allowedFilePolicy: 'Upload the complete reviewed Skill package, including the local registry manifest.',
177
- forbiddenPublicFiles: ['.env', 'credentials', 'node_modules', 'dist', 'build', 'browser profiles', 'SSH keys']
177
+ allowedFilePolicy: 'Upload the complete reviewed Skill package together with the generated no-secret package manifest. Keep the local registry manifest and runtime credentials on the creator device.',
178
+ forbiddenPublicFiles: [WORK_DIR, '.env', 'credentials', 'node_modules', 'dist', 'build', 'browser profiles', 'SSH keys', 'public tokens', 'signing secrets']
178
179
  },
179
180
  red: {
180
181
  label: 'Red Skill',
@@ -1090,11 +1091,16 @@ function shouldIgnorePackageEntry(relativePath, entryName, isDirectory = false)
1090
1091
  if (entryName === '.env' || entryName.startsWith('.env.')) return true;
1091
1092
  if (/\.(pem|key)$/i.test(entryName)) return true;
1092
1093
  if (packageArtifactPrefix && normalized.startsWith(packageArtifactPrefix)) return true;
1093
- if (isDirectory && (normalized === WORK_DIR || normalized === PUBLIC_PROTOCOL_DIR)) return false;
1094
- if (isDirectory && (normalized.startsWith(`${WORK_DIR}/`) || normalized.startsWith(`${PUBLIC_PROTOCOL_DIR}/`))) return false;
1095
- if ((normalized === WORK_DIR || normalized.startsWith(localRegistryPrefix)) && !isXiashePackageRegistryFile(normalized)) {
1094
+ // The local registry workspace carries the public token, signing key and
1095
+ // resumable-upload state. It is intentionally never part of an installable
1096
+ // archive, even for first-party distribution. A separate, no-secret
1097
+ // package manifest is written below `PUBLIC_PROTOCOL_DIR` instead.
1098
+ if (normalized === WORK_DIR || normalized.startsWith(localRegistryPrefix)) {
1096
1099
  return true;
1097
1100
  }
1101
+ if (normalized === PUBLIC_PROTOCOL_DIR || normalized.startsWith(`${PUBLIC_PROTOCOL_DIR}/`)) {
1102
+ return isDirectory ? false : !isXiashePackageRegistryFile(normalized);
1103
+ }
1098
1104
  const otherRegistryDir = WORK_DIR === '.xiashe' ? '.agentpie' : '.xiashe';
1099
1105
  if (normalized === otherRegistryDir || normalized.startsWith(`${otherRegistryDir}/`)) return true;
1100
1106
  return false;
@@ -1103,17 +1109,45 @@ function shouldIgnorePackageEntry(relativePath, entryName, isDirectory = false)
1103
1109
  function isXiashePackageRegistryFile(relativePath) {
1104
1110
  const normalized = String(relativePath || '').replace(/\\/g, '/');
1105
1111
  const allowed = new Set([
1106
- `${WORK_DIR}/${MANIFEST_FILE}`,
1107
- `${WORK_DIR}/AGENT_ACK.md`,
1108
- `${WORK_DIR}/REGISTRY_DISCLOSURE.md`,
1109
- `${WORK_DIR}/runtime-events.js`,
1110
1112
  `${PUBLIC_PROTOCOL_DIR}/AGENT_ACK.md`,
1111
1113
  `${PUBLIC_PROTOCOL_DIR}/REGISTRY_DISCLOSURE.md`,
1112
- `${PUBLIC_PROTOCOL_DIR}/runtime.yaml`
1114
+ `${PUBLIC_PROTOCOL_DIR}/runtime.yaml`,
1115
+ `${PUBLIC_PROTOCOL_DIR}/${PUBLIC_PACKAGE_MANIFEST_FILE}`
1113
1116
  ]);
1114
1117
  return allowed.has(normalized);
1115
1118
  }
1116
1119
 
1120
+ function publicPackageManifestRelativePath() {
1121
+ return `${PUBLIC_PROTOCOL_DIR}/${PUBLIC_PACKAGE_MANIFEST_FILE}`;
1122
+ }
1123
+
1124
+ async function writePublicPackageManifest(root, inspected) {
1125
+ const registry = inspected.registry || {};
1126
+ const outputPath = path.join(root, PUBLIC_PROTOCOL_DIR, PUBLIC_PACKAGE_MANIFEST_FILE);
1127
+ const manifest = {
1128
+ schemaVersion: `${REGISTRY_PROVIDER}.skill.package.v1`,
1129
+ skill: {
1130
+ name: inspected.name,
1131
+ skillKey: inspected.skillKey,
1132
+ description: inspected.description || null,
1133
+ version: inspected.version || null,
1134
+ isPaid: Boolean(inspected.isPaid),
1135
+ requiresEntitlement: Boolean(inspected.requiresEntitlement)
1136
+ },
1137
+ creator: {
1138
+ cardUrl: normalizeText(registry.creatorCardUrl || registry.creatorProfile?.cardUrl, 800) || null
1139
+ },
1140
+ safety: {
1141
+ localRegistryStateIncluded: false,
1142
+ credentialsIncluded: false,
1143
+ signingMaterialIncluded: false
1144
+ }
1145
+ };
1146
+ await mkdir(path.dirname(outputPath), { recursive: true });
1147
+ await writeFile(outputPath, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o644 });
1148
+ return { outputPath, manifest };
1149
+ }
1150
+
1117
1151
  async function walkXiashePackageFiles(root, current = root, out = []) {
1118
1152
  const entries = await readdir(current, { withFileTypes: true });
1119
1153
  for (const entry of entries) {
@@ -1218,8 +1252,9 @@ async function createTarGz(files) {
1218
1252
 
1219
1253
  async function buildXiashePackageArtifact(root, inspected, flags = {}) {
1220
1254
  const absoluteRoot = path.resolve(root || '.');
1255
+ await writePublicPackageManifest(absoluteRoot, inspected);
1221
1256
  const files = await walkXiashePackageFiles(absoluteRoot);
1222
- const manifestRelative = `${WORK_DIR}/${MANIFEST_FILE}`;
1257
+ const manifestRelative = publicPackageManifestRelativePath();
1223
1258
  const skillMarkdownPresent = files.some((file) => /^SKILL(\.[a-z0-9]+)?$/i.test(file.relative));
1224
1259
  const manifestPresent = files.some((file) => file.relative === manifestRelative);
1225
1260
  if (!skillMarkdownPresent) {
@@ -1639,10 +1674,10 @@ async function writeManifest(root, flags) {
1639
1674
 
1640
1675
  function hubInstruction(hub) {
1641
1676
  if (hub === 'agentpie') {
1642
- 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.';
1677
+ return 'AgentPie Registry publish is the full Skill package flow. The local registry manifest stays on the creator device; the installable package contains only the generated no-secret package manifest. Keep public disclosure, attribution, and runtime analytics callbacks; if a creator-authenticated CLI/API session exists, create or reuse the AgentPie registry draft.';
1643
1678
  }
1644
1679
  if (hub === 'xiashe') {
1645
- return '虾舍商店发布是完整 Skill 包和 registry manifest 的主流程。请保留公开披露、归因和 runtime analytics 回传能力;如果本地 manifest registry public token 或已有创作者认证 CLI/API 会话,就创建或复用虾舍商店草稿。';
1680
+ return '虾舍商店发布是完整 Skill 包的主流程。本地 registry manifest 仅保留在创作者设备;安装包只包含自动生成的不含敏感信息的 package manifest。请保留公开披露、归因和 runtime analytics 回传能力;如果已有创作者认证 CLI/API 会话,就创建或复用虾舍商店草稿。';
1646
1681
  }
1647
1682
  if (hub === 'red') {
1648
1683
  return `Red Skill 的官方 uploader.md / skillhub-upload / 页面流程是主流程。请优先使用本机 skillhub-upload;${PRODUCT_NAME} 负责生成平台安全披露、connector/运行时协议和本地 registry handoff,并把 registry id、public token、endpoint 等后台字段保留在本地私有配置或平台私有字段里。`;
@@ -1716,16 +1751,16 @@ function uploadCompatibilityLines(hub, manifestFile, protectedPaidSkill = false)
1716
1751
  if (hub === 'agentpie') {
1717
1752
  return [
1718
1753
  'AgentPie Registry compatibility requirements:',
1719
- `- AgentPie Registry can receive the complete Skill package and ${localManifest} registry manifest.`,
1720
- '- Keep public disclosure text, attribution links, and runtime event callbacks; do not remove the registry manifest.',
1754
+ `- AgentPie Registry receives the complete Skill package. Keep ${localManifest} on the creator device; it is not an installable-package file.`,
1755
+ '- Keep public disclosure text, attribution links, and runtime event callbacks; do not remove the generated public protocol files.',
1721
1756
  '- Before submitting a draft, still exclude .env, keys, node_modules, dist/build, and unrelated local files.'
1722
1757
  ];
1723
1758
  }
1724
1759
  if (hub === 'xiashe') {
1725
1760
  return [
1726
1761
  '虾舍商店兼容性要求:',
1727
- `- 虾舍商店可以接收完整 Skill 包和 ${localManifest} registry manifest。`,
1728
- '- 保留公开披露文本、归因链接和 runtime event callback;不要删除 registry manifest。',
1762
+ `- 虾舍商店接收完整 Skill 包;${localManifest} 仅保留在创作者设备,不属于安装包。`,
1763
+ '- 保留公开披露文本、归因链接和 runtime event callback;不要删除生成的公开协议文件。',
1729
1764
  '- 提交草稿前仍需排除 .env、密钥、node_modules、dist/build 和无关本地文件。'
1730
1765
  ];
1731
1766
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiashe/skill",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "xiashe-skill": "bin/xiashe-skill.mjs"