@xiashe/skill 0.1.26 → 0.1.27
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 +2 -2
- package/bin/xiashe-skill.mjs +89 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,9 +44,9 @@ node packages/xiashe-skill-cli/bin/xiashe-skill.mjs snippet . --target js
|
|
|
44
44
|
node packages/xiashe-skill-cli/bin/xiashe-skill.mjs track . --event skill_invoked --hub red --dry-run --json
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
Use the `claimUrl` returned with a dashboard dynamic code exactly as issued. `publish`
|
|
47
|
+
Use the `claimUrl` returned with a dashboard dynamic code exactly as issued. `publish` validates that destination before it consumes a code, so a code cannot accidentally be sent to a different service. For an existing Skill update, run the normal publish command from the original project folder. The CLI reads and validates its saved local connection before it writes or uploads anything. Do not copy internal endpoint options into a user-facing update task.
|
|
48
48
|
|
|
49
|
-
When an existing project was originally linked through XiaShe, `@agentpie/skill publish`
|
|
49
|
+
When an existing project was originally linked through XiaShe, `@agentpie/skill publish` can reuse that local connection only for an update without a dynamic code or public token. It validates the recorded connection first, then creates a separate AgentPie local connection while retaining the XiaShe original. If it cannot verify the link, it stops before changing files or uploading a package. This keeps distinct services isolated without asking users to understand internal deployment details.
|
|
50
50
|
|
|
51
51
|
## Reliable publish and recovery
|
|
52
52
|
|
package/bin/xiashe-skill.mjs
CHANGED
|
@@ -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.
|
|
71
|
+
const VERSION = process.env.XIASHE_SKILL_CLI_VERSION || '0.1.27';
|
|
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');
|
|
@@ -341,7 +341,7 @@ Usage:
|
|
|
341
341
|
Options:
|
|
342
342
|
--public-token <token> Public write token issued by ${PRODUCT_NAME} registry.
|
|
343
343
|
--code <dynamic-code> One-time ${PRODUCT_NAME} dashboard code used to claim registry identity.
|
|
344
|
-
--registry-origin <url>
|
|
344
|
+
--registry-origin <url> Advanced recovery option for an existing Skill. Normal updates do not need it.
|
|
345
345
|
--claim-url <url> Code claim endpoint. Defaults to XIASHE_SKILL_CLAIM_URL or ${DEFAULT_CLAIM_URL}
|
|
346
346
|
--registry-doctor-url <url> Registry preflight endpoint. Defaults to the claim URL origin.
|
|
347
347
|
--skill-id <id> Public ${PRODUCT_NAME} Skill registry id.
|
|
@@ -543,7 +543,7 @@ function latestVersionEndpoint(inspectedOrRegistry = {}) {
|
|
|
543
543
|
// Existing Skills must keep checking the registry that originally issued
|
|
544
544
|
// their manifest. Falling back to a CLI default here would make a dev
|
|
545
545
|
// package discover Global/CN updates after a machine-level config change.
|
|
546
|
-
const registryOrigin =
|
|
546
|
+
const registryOrigin = resolveStoredRegistryOrigin(registry) || DEFAULT_BASE_URL;
|
|
547
547
|
const params = new URLSearchParams();
|
|
548
548
|
if (publicSkillId) {
|
|
549
549
|
params.set('publicSkillId', publicSkillId);
|
|
@@ -990,13 +990,13 @@ async function resolveExistingSkillRoot(root, flags = {}) {
|
|
|
990
990
|
}
|
|
991
991
|
if (candidates.length > 1) {
|
|
992
992
|
throw new Error(
|
|
993
|
-
'
|
|
994
|
-
'
|
|
993
|
+
'CREATOR_SKILL_SOURCE_AMBIGUOUS: more than one Skill project matches this update. ' +
|
|
994
|
+
'No Skill was changed. Run this task from the intended Skill project folder.'
|
|
995
995
|
);
|
|
996
996
|
}
|
|
997
997
|
throw new Error(
|
|
998
|
-
'
|
|
999
|
-
'
|
|
998
|
+
'CREATOR_SKILL_SOURCE_NOT_FOUND: this task does not include the original Skill project. ' +
|
|
999
|
+
'No Skill was created or changed. Add that project folder and retry.'
|
|
1000
1000
|
);
|
|
1001
1001
|
}
|
|
1002
1002
|
|
|
@@ -1123,11 +1123,14 @@ function claimUrlForCode(flags = {}) {
|
|
|
1123
1123
|
}
|
|
1124
1124
|
|
|
1125
1125
|
function claimUrlForExistingManifest(flags = {}, registry = {}) {
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1126
|
+
const claimUrl = explicitClaimUrl(flags) || claimUrlFromRegistryOrigin(resolveStoredRegistryOrigin(registry));
|
|
1127
|
+
if (!claimUrl) {
|
|
1128
|
+
throw new Error(
|
|
1129
|
+
'CREATOR_SKILL_CONNECTION_UNVERIFIABLE: this local Skill connection cannot be verified safely. ' +
|
|
1130
|
+
'No Skill was created or changed. Add the original Skill project folder and retry.'
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
return claimUrl;
|
|
1131
1134
|
}
|
|
1132
1135
|
|
|
1133
1136
|
function normalizeRegistryOrigin(value) {
|
|
@@ -1154,6 +1157,55 @@ function registryOriginFromFlags(flags = {}) {
|
|
|
1154
1157
|
return normalizeRegistryOrigin(flags['registry-origin']);
|
|
1155
1158
|
}
|
|
1156
1159
|
|
|
1160
|
+
const STORED_REGISTRY_ENDPOINT_PATHS = new Set([
|
|
1161
|
+
'/registry/skill/claim',
|
|
1162
|
+
'/registry/skill-events',
|
|
1163
|
+
'/registry/agent-ack',
|
|
1164
|
+
'/registry/skill/latest',
|
|
1165
|
+
'/registry/skill/package-upload-url',
|
|
1166
|
+
'/registry/skill/package-status'
|
|
1167
|
+
]);
|
|
1168
|
+
|
|
1169
|
+
function registryOriginFromStoredEndpoint(value) {
|
|
1170
|
+
const raw = normalizeText(value, 2_000);
|
|
1171
|
+
if (!raw) return '';
|
|
1172
|
+
let url;
|
|
1173
|
+
try {
|
|
1174
|
+
url = new URL(raw);
|
|
1175
|
+
} catch {
|
|
1176
|
+
return '';
|
|
1177
|
+
}
|
|
1178
|
+
if (url.username || url.password || url.hash) return '';
|
|
1179
|
+
const pathname = url.pathname.replace(/\/+$/, '') || '/';
|
|
1180
|
+
if (!STORED_REGISTRY_ENDPOINT_PATHS.has(pathname)) return '';
|
|
1181
|
+
try {
|
|
1182
|
+
return normalizeRegistryOrigin(url.origin);
|
|
1183
|
+
} catch {
|
|
1184
|
+
return '';
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
function resolveStoredRegistryOrigin(registry = {}) {
|
|
1189
|
+
const directOrigin = normalizeBaseUrl(registry.registryOrigin);
|
|
1190
|
+
if (directOrigin) {
|
|
1191
|
+
try {
|
|
1192
|
+
return normalizeRegistryOrigin(directOrigin);
|
|
1193
|
+
} catch {
|
|
1194
|
+
return '';
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
for (const endpoint of [
|
|
1198
|
+
registry.claimUrl,
|
|
1199
|
+
registry.registryUrl,
|
|
1200
|
+
registry.agentAckUrl,
|
|
1201
|
+
registry.latestVersionEndpoint
|
|
1202
|
+
]) {
|
|
1203
|
+
const origin = registryOriginFromStoredEndpoint(endpoint);
|
|
1204
|
+
if (origin) return origin;
|
|
1205
|
+
}
|
|
1206
|
+
return '';
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1157
1209
|
function applyRegistryOriginFlags(flags = {}) {
|
|
1158
1210
|
const registryOrigin = registryOriginFromFlags(flags);
|
|
1159
1211
|
if (!registryOrigin) return flags;
|
|
@@ -1572,15 +1624,15 @@ async function uploadXiashePackageArtifact(root, flags, manifestResult) {
|
|
|
1572
1624
|
// to the production registry, then verify that origin before any write.
|
|
1573
1625
|
const claimUrl = claimUrlForExistingManifest(flags, registry);
|
|
1574
1626
|
const registryPreflight = await preflightRegistryClaim(claimUrl, flags);
|
|
1575
|
-
const expectedRegistryOrigin =
|
|
1627
|
+
const expectedRegistryOrigin = resolveStoredRegistryOrigin(registry);
|
|
1576
1628
|
const expectedEnvironmentId = normalizeText(registry.environmentId, 160);
|
|
1577
1629
|
if (
|
|
1578
1630
|
(expectedRegistryOrigin && expectedRegistryOrigin !== registryPreflight.registryOrigin) ||
|
|
1579
1631
|
(expectedEnvironmentId && expectedEnvironmentId !== registryPreflight.environmentId)
|
|
1580
1632
|
) {
|
|
1581
1633
|
throw new Error(
|
|
1582
|
-
'
|
|
1583
|
-
'
|
|
1634
|
+
'CREATOR_SKILL_CONNECTION_MISMATCH: this project is linked to a different Skill service. ' +
|
|
1635
|
+
'No package was uploaded.'
|
|
1584
1636
|
);
|
|
1585
1637
|
}
|
|
1586
1638
|
const uploadTicket =
|
|
@@ -1712,22 +1764,25 @@ async function inspectSkill(root, flags = {}) {
|
|
|
1712
1764
|
async function writeManifest(root, flags) {
|
|
1713
1765
|
const inspected = await inspectSkill(root, flags);
|
|
1714
1766
|
const code = normalizeText(flags.code, 80);
|
|
1715
|
-
const
|
|
1716
|
-
const savedRegistryOrigin =
|
|
1767
|
+
const rawExistingRegistry = inspected.registry || {};
|
|
1768
|
+
const savedRegistryOrigin = resolveStoredRegistryOrigin(rawExistingRegistry);
|
|
1769
|
+
const existingRegistry = savedRegistryOrigin && rawExistingRegistry.registryOrigin !== savedRegistryOrigin
|
|
1770
|
+
? { ...rawExistingRegistry, registryOrigin: savedRegistryOrigin }
|
|
1771
|
+
: rawExistingRegistry;
|
|
1717
1772
|
const savedEnvironmentId = normalizeText(existingRegistry.environmentId, 160);
|
|
1718
1773
|
const requestedRegistryOrigin = registryOriginFromFlags(flags);
|
|
1719
1774
|
const suppliedPublicToken = normalizeText(flags['public-token'], 512);
|
|
1720
1775
|
const isLegacyXiaSheMigration = inspected.manifestSource === 'legacy_xiashe';
|
|
1721
1776
|
if (
|
|
1722
1777
|
isLegacyXiaSheMigration &&
|
|
1723
|
-
(existingRegistry.provider !== 'xiashe' || !savedRegistryOrigin
|
|
1778
|
+
(existingRegistry.provider !== 'xiashe' || !savedRegistryOrigin)
|
|
1724
1779
|
) {
|
|
1725
1780
|
throw new Error(
|
|
1726
|
-
'
|
|
1727
|
-
'No AgentPie
|
|
1781
|
+
'CREATOR_SKILL_LEGACY_CONNECTION_UNVERIFIABLE: this older XiaShe Skill connection cannot be verified safely. ' +
|
|
1782
|
+
'No AgentPie Skill was created or changed. Use the original Skill project folder and refresh its connection before updating.'
|
|
1728
1783
|
);
|
|
1729
1784
|
}
|
|
1730
|
-
if (!code && suppliedPublicToken && !explicitClaimUrl(flags) && !
|
|
1785
|
+
if (!code && suppliedPublicToken && !explicitClaimUrl(flags) && !savedRegistryOrigin) {
|
|
1731
1786
|
throw new Error(
|
|
1732
1787
|
'CREATOR_SKILL_CLAIM_URL_REQUIRED: a new manifest created from --public-token must include --claim-url. ' +
|
|
1733
1788
|
'Existing manifests resume through their saved registry origin.'
|
|
@@ -1735,19 +1790,20 @@ async function writeManifest(root, flags) {
|
|
|
1735
1790
|
}
|
|
1736
1791
|
if (!code && !savedRegistryOrigin && !requestedRegistryOrigin) {
|
|
1737
1792
|
throw new Error(
|
|
1738
|
-
'
|
|
1793
|
+
'CREATOR_SKILL_CONNECTION_UNVERIFIABLE: this local Skill connection cannot be verified safely. ' +
|
|
1794
|
+
'No Skill was created or changed. Add the original Skill project folder and retry.'
|
|
1739
1795
|
);
|
|
1740
1796
|
}
|
|
1741
1797
|
if (!code && savedRegistryOrigin && requestedRegistryOrigin && savedRegistryOrigin !== requestedRegistryOrigin) {
|
|
1742
|
-
throw new Error('
|
|
1798
|
+
throw new Error('CREATOR_SKILL_CONNECTION_MISMATCH: this project is linked to a different Skill service. No files were changed.');
|
|
1743
1799
|
}
|
|
1744
1800
|
const claimUrl = code ? claimUrlForCode(flags) : claimUrlForExistingManifest(flags, existingRegistry);
|
|
1745
1801
|
const registryPreflight = await preflightRegistryClaim(claimUrl, flags);
|
|
1746
1802
|
if (!code && savedRegistryOrigin && savedRegistryOrigin !== registryPreflight.registryOrigin) {
|
|
1747
|
-
throw new Error('
|
|
1803
|
+
throw new Error('CREATOR_SKILL_CONNECTION_MISMATCH: this project is linked to a different Skill service. No files were changed.');
|
|
1748
1804
|
}
|
|
1749
1805
|
if (!code && savedEnvironmentId && savedEnvironmentId !== registryPreflight.environmentId) {
|
|
1750
|
-
throw new Error('
|
|
1806
|
+
throw new Error('CREATOR_SKILL_CONNECTION_MISMATCH: this project is linked to a different Skill service. No files were changed.');
|
|
1751
1807
|
}
|
|
1752
1808
|
const claim = code
|
|
1753
1809
|
? await postJson(
|
|
@@ -1778,12 +1834,15 @@ async function writeManifest(root, flags) {
|
|
|
1778
1834
|
const claimEnvironment = normalizeText(claim.registry?.environmentId, 160);
|
|
1779
1835
|
const claimOrigin = normalizeBaseUrl(claim.registry?.registryOrigin);
|
|
1780
1836
|
if (claimEnvironment !== registryPreflight.environmentId || claimOrigin !== registryPreflight.registryOrigin) {
|
|
1781
|
-
throw new Error('
|
|
1837
|
+
throw new Error('CREATOR_SKILL_CONNECTION_MISMATCH: the returned Skill identity does not match this local connection. No package upload was attempted.');
|
|
1782
1838
|
}
|
|
1783
1839
|
}
|
|
1784
1840
|
const publicToken = normalizeText(flags['public-token'] || claim?.publicToken || existingRegistry.publicToken, 512);
|
|
1785
1841
|
if (!publicToken) {
|
|
1786
|
-
throw new Error(
|
|
1842
|
+
throw new Error(
|
|
1843
|
+
'CREATOR_SKILL_CONNECTION_UNVERIFIABLE: this local Skill connection cannot be verified safely. ' +
|
|
1844
|
+
'No Skill was created or changed. Add the original Skill project folder and retry.'
|
|
1845
|
+
);
|
|
1787
1846
|
}
|
|
1788
1847
|
const now = new Date().toISOString();
|
|
1789
1848
|
const claimCreatorProfile = normalizeCreatorProfile(claim?.creatorProfile);
|
|
@@ -3508,7 +3567,7 @@ async function setupAgentWorkflow(root, flags) {
|
|
|
3508
3567
|
? 'An existing local Skill connection was found automatically; no new registry entry was created.'
|
|
3509
3568
|
: null,
|
|
3510
3569
|
manifestResult.adoptedLegacyXiaSheManifest
|
|
3511
|
-
? 'A compatible XiaShe local connection was reused
|
|
3570
|
+
? 'A compatible XiaShe local connection was reused safely; a separate AgentPie local connection was created.'
|
|
3512
3571
|
: null,
|
|
3513
3572
|
firstPartyPackageArtifact?.skipped
|
|
3514
3573
|
? `${PRODUCT_NAME} complete package upload was skipped (${firstPartyPackageArtifact.reason}).`
|
|
@@ -3573,10 +3632,8 @@ async function main() {
|
|
|
3573
3632
|
flags
|
|
3574
3633
|
);
|
|
3575
3634
|
print(flags.json ? result : [
|
|
3576
|
-
`${PRODUCT_NAME}
|
|
3577
|
-
|
|
3578
|
-
`Registry: ${result.registryOrigin}`,
|
|
3579
|
-
`Protocol: ${result.protocolVersion}`
|
|
3635
|
+
`${PRODUCT_NAME} preflight passed.`,
|
|
3636
|
+
'Connection verified.'
|
|
3580
3637
|
].join('\n'), flags.json);
|
|
3581
3638
|
return;
|
|
3582
3639
|
}
|