@xiashe/skill 0.1.1 → 0.1.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/bin/xiashe-skill.mjs +125 -24
- package/package.json +1 -1
package/bin/xiashe-skill.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { createHash } from 'node:crypto';
|
|
3
|
+
import { createHash, createHmac } from 'node:crypto';
|
|
4
4
|
import { existsSync } 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
8
|
|
|
9
|
-
const VERSION = '0.1.
|
|
9
|
+
const VERSION = '0.1.2';
|
|
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,9 @@ 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 DEFAULT_REGISTRY_URL = process.env.XIASHE_SKILL_REGISTRY_URL || `${DEFAULT_BASE_URL}/registry/skill-events`;
|
|
21
21
|
const DEFAULT_CLAIM_URL = process.env.XIASHE_SKILL_CLAIM_URL || `${DEFAULT_BASE_URL}/registry/skill/claim`;
|
|
22
|
+
const EVENT_SCHEMA_VERSION = process.env.XIASHE_SKILL_EVENT_SCHEMA_VERSION || (REGISTRY_PROVIDER === 'agentpie'
|
|
23
|
+
? 'agentpie.skill.event.v1'
|
|
24
|
+
: 'xiashe.skill.event.v1');
|
|
22
25
|
const DEFAULT_IGNORE = new Set([
|
|
23
26
|
'.git',
|
|
24
27
|
'.xiashe',
|
|
@@ -41,11 +44,11 @@ function usage() {
|
|
|
41
44
|
|
|
42
45
|
Usage:
|
|
43
46
|
${COMMAND_NAME} inspect [skill-dir] [--json]
|
|
44
|
-
${COMMAND_NAME} setup [skill-dir] --code <dynamic-code> --hub <red|clawhub|skillhub|generic>
|
|
45
|
-
${COMMAND_NAME} setup [skill-dir] --public-token <token> --skill-id <id> --hub <red|clawhub|skillhub|generic>
|
|
47
|
+
${COMMAND_NAME} setup [skill-dir] --code <dynamic-code> --hub <red|clawhub|skillhub|claude|dify|generic>
|
|
48
|
+
${COMMAND_NAME} setup [skill-dir] --public-token <token> --skill-id <id> --hub <red|clawhub|skillhub|claude|dify|generic>
|
|
46
49
|
${COMMAND_NAME} attach [skill-dir] --code <dynamic-code> [--name <name>]
|
|
47
50
|
${COMMAND_NAME} attach [skill-dir] --public-token <token> [--skill-id <id>] [--name <name>]
|
|
48
|
-
${COMMAND_NAME} prompt [skill-dir] --hub <red|clawhub|skillhub|generic> [--source-url <url>] [--out <file>]
|
|
51
|
+
${COMMAND_NAME} prompt [skill-dir] --hub <red|clawhub|skillhub|claude|dify|generic> [--source-url <url>] [--out <file>]
|
|
49
52
|
${COMMAND_NAME} snippet [skill-dir] [--target js|curl] [--out <file>]
|
|
50
53
|
${COMMAND_NAME} track [skill-dir] --event <event> [--hub <hub>] [--installation-id <id>] [--invocation-id <id>]
|
|
51
54
|
|
|
@@ -57,7 +60,7 @@ Options:
|
|
|
57
60
|
--registry-url <url> Event endpoint written to the manifest.
|
|
58
61
|
--name <name> Skill display name override.
|
|
59
62
|
--description <text> Skill description override.
|
|
60
|
-
--hub <hub> Target Skill hub prompt style: red, clawhub, skillhub, or generic.
|
|
63
|
+
--hub <hub> Target Skill hub prompt style: red, clawhub, skillhub, claude, dify, or generic.
|
|
61
64
|
--event <event> Runtime event to submit for testing.
|
|
62
65
|
--installation-id <id> Stable anonymous install id for runtime analytics.
|
|
63
66
|
--invocation-id <id> Unique invocation id for one skill call.
|
|
@@ -67,6 +70,7 @@ Options:
|
|
|
67
70
|
--platform-prompt-file <p> Official third-party hub prompt file to embed in the handoff.
|
|
68
71
|
--platform-command <cmd> Official third-party hub CLI/upload command to include.
|
|
69
72
|
--manifest-path <path> Registry manifest output path. Defaults to ${MANIFEST_FILE} for attach, ${WORK_DIR}/${MANIFEST_FILE} for setup.
|
|
73
|
+
--signing-secret <secret> Optional HMAC secret for signed runtime events.
|
|
70
74
|
--source-url <url> User-provided source URL an Agent can use during third-party upload.
|
|
71
75
|
--package-url <url> Deprecated alias for --source-url.
|
|
72
76
|
--out <path> Output prompt or snippet file.
|
|
@@ -144,6 +148,26 @@ function safeSkillKey(value) {
|
|
|
144
148
|
.replace(/^-+|-+$/g, '') || 'skill';
|
|
145
149
|
}
|
|
146
150
|
|
|
151
|
+
function canonicalSignaturePayload(payload) {
|
|
152
|
+
return [
|
|
153
|
+
payload.schemaVersion || EVENT_SCHEMA_VERSION,
|
|
154
|
+
payload.eventType || '',
|
|
155
|
+
payload.idempotencyKey || '',
|
|
156
|
+
Number.isFinite(payload.occurredAt) ? String(Math.floor(payload.occurredAt)) : '',
|
|
157
|
+
payload.installationId || '',
|
|
158
|
+
payload.invocationId || '',
|
|
159
|
+
payload.hub || '',
|
|
160
|
+
payload.skillKey || ''
|
|
161
|
+
].join('\n');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function signEventPayload(payload, signingSecret) {
|
|
165
|
+
if (!signingSecret) return undefined;
|
|
166
|
+
return createHmac('sha256', signingSecret)
|
|
167
|
+
.update(canonicalSignaturePayload(payload))
|
|
168
|
+
.digest('hex');
|
|
169
|
+
}
|
|
170
|
+
|
|
147
171
|
async function readJsonFile(filePath) {
|
|
148
172
|
if (!existsSync(filePath)) return null;
|
|
149
173
|
try {
|
|
@@ -307,6 +331,11 @@ async function writeManifest(root, flags) {
|
|
|
307
331
|
skillId: normalizeText(flags['skill-id'] || claim?.skillId, 160) || null,
|
|
308
332
|
publicToken,
|
|
309
333
|
registryUrl: normalizeText(flags['registry-url'] || claim?.registryUrl, 800) || DEFAULT_REGISTRY_URL,
|
|
334
|
+
eventSchemaVersion: EVENT_SCHEMA_VERSION,
|
|
335
|
+
signing: {
|
|
336
|
+
mode: normalizeText(flags['signing-secret'], 20) ? 'optional' : 'off',
|
|
337
|
+
secretEnv: `${REGISTRY_PROVIDER.toUpperCase()}_SKILL_SIGNING_SECRET`
|
|
338
|
+
},
|
|
310
339
|
analytics: {
|
|
311
340
|
enabled: true,
|
|
312
341
|
allowedEvents: [
|
|
@@ -349,6 +378,12 @@ function hubInstruction(hub) {
|
|
|
349
378
|
if (hub === 'skillhub') {
|
|
350
379
|
return 'SkillHub 的官方 CLI、prompt 或页面流程是主流程。请先确认 SkillHub 当前要求,再把下面的虾舍 registry 要求作为附加说明合并进去。';
|
|
351
380
|
}
|
|
381
|
+
if (hub === 'claude') {
|
|
382
|
+
return 'Claude Skills 的官方上传/导入流程是主流程。请先确认 Claude 当前 Skill 格式和共享要求,再把下面的 registry 披露文本放入允许的说明文件。';
|
|
383
|
+
}
|
|
384
|
+
if (hub === 'dify') {
|
|
385
|
+
return 'Dify Plugin/Tool 的官方打包和发布流程是主流程。请先按 Dify 插件规范处理 manifest 和工具定义,再把下面的 registry 披露文本放入允许的 README/说明字段。';
|
|
386
|
+
}
|
|
352
387
|
return '目标 Skill Hub 的官方 CLI、prompt 或页面流程是主流程。请先确认平台当前要求,再把下面的虾舍 registry 要求作为附加说明合并进去。';
|
|
353
388
|
}
|
|
354
389
|
|
|
@@ -362,6 +397,12 @@ function platformPromptPlaceholder(hub) {
|
|
|
362
397
|
if (hub === 'skillhub') {
|
|
363
398
|
return '如果 SkillHub 提供官方 CLI 命令或上传 prompt,请优先使用官方命令/prompt;不要用虾舍 prompt 替代 SkillHub 官方流程。';
|
|
364
399
|
}
|
|
400
|
+
if (hub === 'claude') {
|
|
401
|
+
return '如果 Claude 提供官方 Skill 导入/上传说明,请优先使用官方说明;不要用虾舍 prompt 替代 Claude 官方流程。';
|
|
402
|
+
}
|
|
403
|
+
if (hub === 'dify') {
|
|
404
|
+
return '如果 Dify 提供官方插件打包/发布命令,请优先使用官方命令;不要用虾舍 prompt 替代 Dify 官方流程。';
|
|
405
|
+
}
|
|
365
406
|
return '如果目标平台提供官方 CLI 命令或上传 prompt,请优先使用官方命令/prompt;不要用虾舍 prompt 替代平台官方流程。';
|
|
366
407
|
}
|
|
367
408
|
|
|
@@ -424,15 +465,18 @@ async function uploadPrompt(inspected, flags) {
|
|
|
424
465
|
const registryUrl = registry.registryUrl || DEFAULT_REGISTRY_URL;
|
|
425
466
|
const eventPayload = {
|
|
426
467
|
publicToken: registry.publicToken || '<xiashe public token from xiashe.skill.json>',
|
|
468
|
+
schemaVersion: registry.eventSchemaVersion || EVENT_SCHEMA_VERSION,
|
|
427
469
|
eventType: 'hub_upload_succeeded',
|
|
428
470
|
hub,
|
|
429
471
|
skillKey: inspected.skillKey,
|
|
472
|
+
idempotencyKey: '<hub-upload-succeeded-stable-key>',
|
|
430
473
|
packageSha256: inspected.package.sha256,
|
|
431
474
|
platformSkillUrl: '<published skill url>',
|
|
432
475
|
scenario: '<short usage scenario if the hub asks for one>'
|
|
433
476
|
};
|
|
434
477
|
const runtimePayload = {
|
|
435
478
|
publicToken: registry.publicToken || '<public token from registry manifest>',
|
|
479
|
+
schemaVersion: registry.eventSchemaVersion || EVENT_SCHEMA_VERSION,
|
|
436
480
|
eventType: 'skill_invoked',
|
|
437
481
|
eventSource: 'runtime',
|
|
438
482
|
runtimeKind: '<mcp|api|agent|webhook|platform>',
|
|
@@ -440,6 +484,7 @@ async function uploadPrompt(inspected, flags) {
|
|
|
440
484
|
skillKey: inspected.skillKey,
|
|
441
485
|
installationId: '<stable anonymous install id>',
|
|
442
486
|
invocationId: '<unique invocation id>',
|
|
487
|
+
idempotencyKey: '<unique invocation id>:skill_invoked',
|
|
443
488
|
scenario: '<short usage scenario label only>',
|
|
444
489
|
sourceSurface: '<profile|hub|agent|direct>',
|
|
445
490
|
campaign: '<optional promotion label>'
|
|
@@ -527,6 +572,7 @@ async function writeRuntimeSnippet(root, flags) {
|
|
|
527
572
|
const registry = inspected.registry || {};
|
|
528
573
|
const registryUrl = registry.registryUrl || DEFAULT_REGISTRY_URL;
|
|
529
574
|
const publicToken = registry.publicToken || '<public token from registry manifest>';
|
|
575
|
+
const eventSchemaVersion = registry.eventSchemaVersion || EVENT_SCHEMA_VERSION;
|
|
530
576
|
const target = normalizeText(flags.target || 'js', 20).toLowerCase();
|
|
531
577
|
const snippet = target === 'curl'
|
|
532
578
|
? [
|
|
@@ -534,6 +580,7 @@ async function writeRuntimeSnippet(root, flags) {
|
|
|
534
580
|
" -H 'content-type: application/json' \\",
|
|
535
581
|
' -d ' + JSON.stringify(JSON.stringify({
|
|
536
582
|
publicToken,
|
|
583
|
+
schemaVersion: eventSchemaVersion,
|
|
537
584
|
eventType: 'skill_invoked',
|
|
538
585
|
eventSource: 'runtime',
|
|
539
586
|
runtimeKind: 'mcp',
|
|
@@ -541,31 +588,62 @@ async function writeRuntimeSnippet(root, flags) {
|
|
|
541
588
|
skillKey: inspected.skillKey,
|
|
542
589
|
installationId: '<anonymous-stable-install-id>',
|
|
543
590
|
invocationId: '<unique-call-id>',
|
|
591
|
+
idempotencyKey: '<unique-call-id>:skill_invoked',
|
|
544
592
|
scenario: '<short-scenario-label>'
|
|
545
593
|
}))
|
|
546
594
|
].join('\n')
|
|
547
595
|
: [
|
|
548
596
|
`const XIASHE_SKILL_REGISTRY_URL = ${JSON.stringify(registryUrl)};`,
|
|
549
597
|
`const XIASHE_SKILL_PUBLIC_TOKEN = ${JSON.stringify(publicToken)};`,
|
|
598
|
+
`const XIASHE_SKILL_EVENT_SCHEMA_VERSION = ${JSON.stringify(eventSchemaVersion)};`,
|
|
599
|
+
`const XIASHE_SKILL_SIGNING_SECRET = ${JSON.stringify(normalizeText(flags['signing-secret'], 512))} || globalThis.process?.env?.XIASHE_SKILL_SIGNING_SECRET || globalThis.process?.env?.AGENTPIE_SKILL_SIGNING_SECRET || '';`,
|
|
600
|
+
'',
|
|
601
|
+
'async function hmacSha256(secret, message) {',
|
|
602
|
+
' if (!secret || !globalThis.crypto?.subtle) return undefined;',
|
|
603
|
+
" const key = await crypto.subtle.importKey('raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);",
|
|
604
|
+
' const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(message));',
|
|
605
|
+
" return Array.from(new Uint8Array(signature)).map((byte) => byte.toString(16).padStart(2, '0')).join('');",
|
|
606
|
+
'}',
|
|
607
|
+
'',
|
|
608
|
+
'function canonicalSignaturePayload(payload) {',
|
|
609
|
+
' return [',
|
|
610
|
+
' payload.schemaVersion || XIASHE_SKILL_EVENT_SCHEMA_VERSION,',
|
|
611
|
+
" payload.eventType || '',",
|
|
612
|
+
" payload.idempotencyKey || '',",
|
|
613
|
+
" Number.isFinite(payload.occurredAt) ? String(Math.floor(payload.occurredAt)) : '',",
|
|
614
|
+
" payload.installationId || '',",
|
|
615
|
+
" payload.invocationId || '',",
|
|
616
|
+
" payload.hub || '',",
|
|
617
|
+
" payload.skillKey || ''",
|
|
618
|
+
" ].join('\\n');",
|
|
619
|
+
'}',
|
|
550
620
|
'',
|
|
551
621
|
'export async function trackSkillEvent(eventType, options = {}) {',
|
|
622
|
+
' const occurredAt = options.occurredAt || Date.now();',
|
|
623
|
+
' const invocationId = options.invocationId;',
|
|
624
|
+
' const payload = {',
|
|
625
|
+
' publicToken: XIASHE_SKILL_PUBLIC_TOKEN,',
|
|
626
|
+
' schemaVersion: XIASHE_SKILL_EVENT_SCHEMA_VERSION,',
|
|
627
|
+
' eventType,',
|
|
628
|
+
" eventSource: options.eventSource || 'runtime',",
|
|
629
|
+
" runtimeKind: options.runtimeKind || 'mcp',",
|
|
630
|
+
` skillKey: ${JSON.stringify(inspected.skillKey)},`,
|
|
631
|
+
' hub: options.hub,',
|
|
632
|
+
' installationId: options.installationId,',
|
|
633
|
+
' invocationId,',
|
|
634
|
+
' idempotencyKey: options.idempotencyKey || `${invocationId || options.installationId || "runtime"}:${eventType}:${occurredAt}`,',
|
|
635
|
+
' scenario: options.scenario,',
|
|
636
|
+
' sourceSurface: options.sourceSurface,',
|
|
637
|
+
' campaign: options.campaign,',
|
|
638
|
+
' packageSha256: options.packageSha256,',
|
|
639
|
+
' occurredAt',
|
|
640
|
+
' };',
|
|
641
|
+
' const signature = await hmacSha256(XIASHE_SKILL_SIGNING_SECRET, canonicalSignaturePayload(payload));',
|
|
642
|
+
' if (signature) payload.signature = signature;',
|
|
552
643
|
' await fetch(XIASHE_SKILL_REGISTRY_URL, {',
|
|
553
644
|
" method: 'POST',",
|
|
554
645
|
" headers: { 'content-type': 'application/json' },",
|
|
555
|
-
' body: JSON.stringify(
|
|
556
|
-
' publicToken: XIASHE_SKILL_PUBLIC_TOKEN,',
|
|
557
|
-
' eventType,',
|
|
558
|
-
" eventSource: options.eventSource || 'runtime',",
|
|
559
|
-
" runtimeKind: options.runtimeKind || 'mcp',",
|
|
560
|
-
` skillKey: ${JSON.stringify(inspected.skillKey)},`,
|
|
561
|
-
' hub: options.hub,',
|
|
562
|
-
' installationId: options.installationId,',
|
|
563
|
-
' invocationId: options.invocationId,',
|
|
564
|
-
' scenario: options.scenario,',
|
|
565
|
-
' sourceSurface: options.sourceSurface,',
|
|
566
|
-
' campaign: options.campaign,',
|
|
567
|
-
' packageSha256: options.packageSha256',
|
|
568
|
-
' })',
|
|
646
|
+
' body: JSON.stringify(payload)',
|
|
569
647
|
' });',
|
|
570
648
|
'}',
|
|
571
649
|
'',
|
|
@@ -595,22 +673,33 @@ async function submitTrackEvent(root, flags) {
|
|
|
595
673
|
if (!eventType) {
|
|
596
674
|
throw new Error('Missing --event.');
|
|
597
675
|
}
|
|
676
|
+
const occurredAt = Number(flags['occurred-at'] || Date.now());
|
|
677
|
+
const invocationId = normalizeText(flags['invocation-id'] || `cli-${Date.now()}`, 160);
|
|
678
|
+
const installationId = normalizeText(flags['installation-id'] || 'local-test-install', 220);
|
|
679
|
+
const hub = normalizeText(flags.hub || 'local-test', 80);
|
|
598
680
|
const payload = {
|
|
599
681
|
publicToken,
|
|
682
|
+
schemaVersion: normalizeText(flags['schema-version'], 80) || EVENT_SCHEMA_VERSION,
|
|
600
683
|
eventType,
|
|
601
684
|
eventSource: normalizeText(flags['event-source'] || 'manual', 40),
|
|
602
685
|
runtimeKind: normalizeText(flags['runtime-kind'] || 'cli-test', 80),
|
|
603
|
-
hub
|
|
686
|
+
hub,
|
|
604
687
|
skillKey: inspected.skillKey,
|
|
605
|
-
installationId
|
|
606
|
-
invocationId
|
|
688
|
+
installationId,
|
|
689
|
+
invocationId,
|
|
607
690
|
scenario: normalizeText(flags.scenario || 'local-test', 120),
|
|
608
691
|
sourceSurface: normalizeText(flags['source-surface'] || 'cli', 120),
|
|
609
692
|
campaign: normalizeText(flags.campaign, 120) || undefined,
|
|
610
693
|
platformSkillUrl: normalizeText(flags['platform-skill-url'], 1000) || undefined,
|
|
611
694
|
packageSha256: inspected.package.sha256,
|
|
612
|
-
idempotencyKey: normalizeText(flags.idempotencyKey || flags['idempotency-key'], 220) ||
|
|
695
|
+
idempotencyKey: normalizeText(flags.idempotencyKey || flags['idempotency-key'], 220) || `${invocationId}:${eventType}`,
|
|
696
|
+
occurredAt: Number.isFinite(occurredAt) ? occurredAt : Date.now()
|
|
613
697
|
};
|
|
698
|
+
const signingSecret = normalizeText(flags['signing-secret'], 512);
|
|
699
|
+
const signature = signEventPayload(payload, signingSecret);
|
|
700
|
+
if (signature) {
|
|
701
|
+
payload.signature = signature;
|
|
702
|
+
}
|
|
614
703
|
if (flags.dryRun) {
|
|
615
704
|
return { ok: true, dryRun: true, registryUrl, payload };
|
|
616
705
|
}
|
|
@@ -631,6 +720,15 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
631
720
|
|
|
632
721
|
const promptPath = path.join(outDir, `upload-${safeSkillKey(hub)}.md`);
|
|
633
722
|
const promptResult = await writePrompt(absoluteRoot, { ...flags, hub, out: promptPath });
|
|
723
|
+
const inspectedAfterManifest = await inspectSkill(absoluteRoot, flags);
|
|
724
|
+
const disclosurePath = path.join(outDir, 'REGISTRY_DISCLOSURE.md');
|
|
725
|
+
await writeFile(
|
|
726
|
+
disclosurePath,
|
|
727
|
+
`${publicDisclosure(inspectedAfterManifest, inspectedAfterManifest.registry?.registryUrl || DEFAULT_REGISTRY_URL)
|
|
728
|
+
.filter((line) => line !== '公开披露文本:' && line !== '```markdown' && line !== '```')
|
|
729
|
+
.join('\n')}\n`,
|
|
730
|
+
{ mode: 0o600 }
|
|
731
|
+
);
|
|
634
732
|
const snippetPath = path.join(outDir, 'runtime-events.js');
|
|
635
733
|
let snippetResult = null;
|
|
636
734
|
if (!flags['no-snippet']) {
|
|
@@ -663,12 +761,14 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
663
761
|
hub,
|
|
664
762
|
manifestPath: manifestResult.manifestPath,
|
|
665
763
|
promptPath: typeof promptResult === 'string' ? promptPath : promptResult.outPath,
|
|
764
|
+
disclosurePath,
|
|
666
765
|
snippetPath: snippetResult ? snippetResult.outPath : null,
|
|
667
766
|
promptEvent,
|
|
668
767
|
warnings,
|
|
669
768
|
next: [
|
|
670
769
|
`Open ${path.relative(absoluteRoot, promptPath)} and merge it with the official ${hub} upload prompt/CLI flow.`,
|
|
671
770
|
`If ${hub} provides its own upload prompt or CLI, treat that official flow as authoritative.`,
|
|
771
|
+
`Use ${path.relative(absoluteRoot, disclosurePath)} as the read-only analytics disclosure for platform review.`,
|
|
672
772
|
'Do not upload secrets, .env files, browser data, SSH keys, node_modules, dist, build, or unrelated local files.',
|
|
673
773
|
`If the Skill is published, record the public URL with: ${COMMAND_NAME} track . --event hub_upload_succeeded --hub ${hub} --platform-skill-url <url>`,
|
|
674
774
|
snippetResult
|
|
@@ -707,6 +807,7 @@ async function main() {
|
|
|
707
807
|
const lines = [
|
|
708
808
|
`Wrote ${result.manifestPath}`,
|
|
709
809
|
`Wrote ${result.promptPath}`,
|
|
810
|
+
`Wrote ${result.disclosurePath}`,
|
|
710
811
|
result.snippetPath ? `Wrote ${result.snippetPath}` : null,
|
|
711
812
|
...result.warnings.map((warning) => `Warning: ${warning}`),
|
|
712
813
|
'',
|