@xiashe/skill 0.1.2 → 0.1.4
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 +63 -4
- package/package.json +1 -1
package/bin/xiashe-skill.mjs
CHANGED
|
@@ -6,13 +6,13 @@ 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.4';
|
|
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');
|
|
13
13
|
const DEFAULT_BASE_URL = process.env.XIASHE_SKILL_DEFAULT_BASE_URL || (COMMAND_NAME === 'agentpie-skill'
|
|
14
|
-
? 'https://
|
|
15
|
-
: 'https://
|
|
14
|
+
? 'https://actions.agentpie.app'
|
|
15
|
+
: 'https://actions.xiashe.chat');
|
|
16
16
|
const MANIFEST_FILE = process.env.XIASHE_SKILL_MANIFEST_FILE || (COMMAND_NAME === 'agentpie-skill'
|
|
17
17
|
? 'agentpie.skill.json'
|
|
18
18
|
: 'xiashe.skill.json');
|
|
@@ -75,6 +75,8 @@ Options:
|
|
|
75
75
|
--package-url <url> Deprecated alias for --source-url.
|
|
76
76
|
--out <path> Output prompt or snippet file.
|
|
77
77
|
--out-dir <path> Output directory for setup artifacts. Defaults to ${WORK_DIR}/.
|
|
78
|
+
--embed-skill-md Also write a clearly marked registry section into SKILL.md.
|
|
79
|
+
--no-skill-md Do not write registry text into SKILL.md. Red hub embeds by default.
|
|
78
80
|
--no-snippet Setup should skip writing the runtime analytics snippet.
|
|
79
81
|
--no-track Setup should skip sending upload_prompt_generated.
|
|
80
82
|
--dry-run Print planned event payloads without network writes.
|
|
@@ -91,7 +93,7 @@ function fail(message, code = 1) {
|
|
|
91
93
|
|
|
92
94
|
function parseArgs(argv) {
|
|
93
95
|
const args = { _: [], json: false, dryRun: false };
|
|
94
|
-
const booleanFlags = new Set(['no-snippet', 'no-track']);
|
|
96
|
+
const booleanFlags = new Set(['embed-skill-md', 'no-skill-md', 'no-snippet', 'no-track']);
|
|
95
97
|
for (let i = 0; i < argv.length; i += 1) {
|
|
96
98
|
const value = argv[i];
|
|
97
99
|
if (value === '--help' || value === '-h') {
|
|
@@ -442,6 +444,55 @@ function publicDisclosure(inspected, registryUrl) {
|
|
|
442
444
|
];
|
|
443
445
|
}
|
|
444
446
|
|
|
447
|
+
function skillMdRegistryBlock(inspected, hub) {
|
|
448
|
+
const registry = inspected.registry || {};
|
|
449
|
+
const registryUrl = registry.registryUrl || DEFAULT_REGISTRY_URL;
|
|
450
|
+
const publicToken = registry.publicToken || '<public token from registry manifest>';
|
|
451
|
+
const marker = `${REGISTRY_PROVIDER}-registry`;
|
|
452
|
+
return [
|
|
453
|
+
`<!-- ${marker}:start -->`,
|
|
454
|
+
`## ${PRODUCT_NAME} Registry / Analytics`,
|
|
455
|
+
'',
|
|
456
|
+
`This Skill is explicitly registered by its creator with ${PRODUCT_NAME} for public attribution and aggregated analytics.`,
|
|
457
|
+
'',
|
|
458
|
+
`- Registry provider: ${REGISTRY_PROVIDER}`,
|
|
459
|
+
`- Skill key: ${inspected.skillKey}`,
|
|
460
|
+
`- Target hub: ${hub}`,
|
|
461
|
+
`- Registry event endpoint: ${registryUrl}`,
|
|
462
|
+
`- Public write token: ${publicToken}`,
|
|
463
|
+
`- Event schema version: ${registry.eventSchemaVersion || EVENT_SCHEMA_VERSION}`,
|
|
464
|
+
`- Source fingerprint: ${inspected.package.sha256}`,
|
|
465
|
+
'',
|
|
466
|
+
'Analytics boundary:',
|
|
467
|
+
'- The public token can only submit allowed aggregate analytics events. It cannot read creator data or administer the account.',
|
|
468
|
+
'- Events should include only public metadata: hub, sourceSurface, campaign, scenario, anonymous installationId, invocationId, and status.',
|
|
469
|
+
'- Do not send user prompts, private files, credentials, environment variables, account tokens, raw business content, or personal identifiers.',
|
|
470
|
+
'- The creator can rotate/revoke the token or disable analytics from the dashboard.',
|
|
471
|
+
'',
|
|
472
|
+
'Recommended runtime events, if the target platform supports callbacks:',
|
|
473
|
+
'- `runtime_install_seen` when a stable anonymous installation is first observed.',
|
|
474
|
+
'- `skill_invoked` when a Skill invocation starts.',
|
|
475
|
+
'- `skill_completed` when an invocation completes.',
|
|
476
|
+
'- `skill_failed` when an invocation fails.',
|
|
477
|
+
'',
|
|
478
|
+
`<!-- ${marker}:end -->`
|
|
479
|
+
].join('\n');
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
async function writeSkillMdRegistryBlock(root, inspected, hub) {
|
|
483
|
+
const skillMdPath = path.join(root, 'SKILL.md');
|
|
484
|
+
const existing = existsSync(skillMdPath)
|
|
485
|
+
? await readFile(skillMdPath, 'utf8')
|
|
486
|
+
: `# ${inspected.name}\n\n${inspected.description || ''}\n`;
|
|
487
|
+
const block = skillMdRegistryBlock(inspected, hub);
|
|
488
|
+
const pattern = /<!-- (?:xiashe|agentpie)-registry:start -->[\s\S]*?<!-- (?:xiashe|agentpie)-registry:end -->/m;
|
|
489
|
+
const next = pattern.test(existing)
|
|
490
|
+
? existing.replace(pattern, block)
|
|
491
|
+
: `${existing.trimEnd()}\n\n${block}\n`;
|
|
492
|
+
await writeFile(skillMdPath, next, { mode: 0o600 });
|
|
493
|
+
return skillMdPath;
|
|
494
|
+
}
|
|
495
|
+
|
|
445
496
|
async function readPlatformPrompt(flags) {
|
|
446
497
|
const promptPath = normalizeText(flags['platform-prompt-file'], 1000);
|
|
447
498
|
if (!promptPath) return '';
|
|
@@ -721,6 +772,10 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
721
772
|
const promptPath = path.join(outDir, `upload-${safeSkillKey(hub)}.md`);
|
|
722
773
|
const promptResult = await writePrompt(absoluteRoot, { ...flags, hub, out: promptPath });
|
|
723
774
|
const inspectedAfterManifest = await inspectSkill(absoluteRoot, flags);
|
|
775
|
+
const shouldEmbedSkillMd = Boolean(flags['embed-skill-md']) || (hub === 'red' && !flags['no-skill-md']);
|
|
776
|
+
const skillMdPath = shouldEmbedSkillMd
|
|
777
|
+
? await writeSkillMdRegistryBlock(absoluteRoot, inspectedAfterManifest, hub)
|
|
778
|
+
: null;
|
|
724
779
|
const disclosurePath = path.join(outDir, 'REGISTRY_DISCLOSURE.md');
|
|
725
780
|
await writeFile(
|
|
726
781
|
disclosurePath,
|
|
@@ -761,6 +816,7 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
761
816
|
hub,
|
|
762
817
|
manifestPath: manifestResult.manifestPath,
|
|
763
818
|
promptPath: typeof promptResult === 'string' ? promptPath : promptResult.outPath,
|
|
819
|
+
skillMdPath,
|
|
764
820
|
disclosurePath,
|
|
765
821
|
snippetPath: snippetResult ? snippetResult.outPath : null,
|
|
766
822
|
promptEvent,
|
|
@@ -768,6 +824,9 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
768
824
|
next: [
|
|
769
825
|
`Open ${path.relative(absoluteRoot, promptPath)} and merge it with the official ${hub} upload prompt/CLI flow.`,
|
|
770
826
|
`If ${hub} provides its own upload prompt or CLI, treat that official flow as authoritative.`,
|
|
827
|
+
skillMdPath
|
|
828
|
+
? `Registry disclosure was also embedded into ${path.relative(absoluteRoot, skillMdPath)} for restrictive hubs.`
|
|
829
|
+
: `If the hub rejects extra files, rerun with --embed-skill-md to place registry disclosure inside SKILL.md.`,
|
|
771
830
|
`Use ${path.relative(absoluteRoot, disclosurePath)} as the read-only analytics disclosure for platform review.`,
|
|
772
831
|
'Do not upload secrets, .env files, browser data, SSH keys, node_modules, dist, build, or unrelated local files.',
|
|
773
832
|
`If the Skill is published, record the public URL with: ${COMMAND_NAME} track . --event hub_upload_succeeded --hub ${hub} --platform-skill-url <url>`,
|