@elisym/cli 0.27.0 → 0.28.0
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/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { generateSecretKey, getPublicKey, nip19, verifyEvent } from 'nostr-tools
|
|
|
9
9
|
import YAML2 from 'yaml';
|
|
10
10
|
import { Command } from 'commander';
|
|
11
11
|
import { mkdir, writeFile, readFile, mkdtemp, rm, rename, stat } from 'node:fs/promises';
|
|
12
|
-
import { parseSkillMd, validateSkillFrontmatter, DEFAULT_X402_MAX_INPUT_BYTES, resolveInsidePathReal, DEFAULT_SCRIPT_TIMEOUT_MS, DynamicScriptSkill as DynamicScriptSkill$1, StaticScriptSkill as StaticScriptSkill$1, StaticFileSkill as StaticFileSkill$1, ScriptSkill as ScriptSkill$1 } from '@elisym/sdk/skills';
|
|
12
|
+
import { parseSkillMd, validateSkillFrontmatter, DEFAULT_X402_MAX_INPUT_BYTES, resolveInsidePathReal, DEFAULT_SCRIPT_TIMEOUT_MS, OnchainCallSkill, DynamicScriptSkill as DynamicScriptSkill$1, StaticScriptSkill as StaticScriptSkill$1, StaticFileSkill as StaticFileSkill$1, ScriptSkill as ScriptSkill$1 } from '@elisym/sdk/skills';
|
|
13
13
|
import chalk from 'chalk';
|
|
14
14
|
import Decimal from 'decimal.js-light';
|
|
15
15
|
import { decodePaymentRequiredHeader } from '@x402/core/http';
|
|
@@ -6704,6 +6704,51 @@ var DynamicScriptSkill = class {
|
|
|
6704
6704
|
return this.inner.execute(input, ctx);
|
|
6705
6705
|
}
|
|
6706
6706
|
};
|
|
6707
|
+
var OnchainSkill = class {
|
|
6708
|
+
name;
|
|
6709
|
+
description;
|
|
6710
|
+
capabilities;
|
|
6711
|
+
priceSubunits;
|
|
6712
|
+
asset;
|
|
6713
|
+
mode = "onchain";
|
|
6714
|
+
image;
|
|
6715
|
+
imageFile;
|
|
6716
|
+
dir;
|
|
6717
|
+
llmOverride;
|
|
6718
|
+
onchain;
|
|
6719
|
+
inner;
|
|
6720
|
+
constructor(params) {
|
|
6721
|
+
this.name = params.name;
|
|
6722
|
+
this.description = params.description;
|
|
6723
|
+
this.capabilities = params.capabilities;
|
|
6724
|
+
this.priceSubunits = params.priceSubunits;
|
|
6725
|
+
this.asset = params.asset;
|
|
6726
|
+
this.image = params.image;
|
|
6727
|
+
this.imageFile = params.imageFile;
|
|
6728
|
+
this.dir = params.dir;
|
|
6729
|
+
this.llmOverride = params.llmOverride;
|
|
6730
|
+
this.onchain = params.onchain;
|
|
6731
|
+
this.inner = new OnchainCallSkill({
|
|
6732
|
+
name: params.name,
|
|
6733
|
+
description: params.description,
|
|
6734
|
+
capabilities: params.capabilities,
|
|
6735
|
+
priceSubunits: BigInt(Math.round(params.priceSubunits)),
|
|
6736
|
+
asset: params.asset,
|
|
6737
|
+
scriptPath: params.scriptPath,
|
|
6738
|
+
scriptArgs: params.scriptArgs,
|
|
6739
|
+
scriptTimeoutMs: params.scriptTimeoutMs,
|
|
6740
|
+
scriptEnv: params.scriptEnv,
|
|
6741
|
+
image: params.image,
|
|
6742
|
+
imageFile: params.imageFile,
|
|
6743
|
+
llmOverride: params.llmOverride,
|
|
6744
|
+
onchain: params.onchain,
|
|
6745
|
+
network: params.network
|
|
6746
|
+
});
|
|
6747
|
+
}
|
|
6748
|
+
async execute(input, ctx) {
|
|
6749
|
+
return this.inner.execute(input, ctx);
|
|
6750
|
+
}
|
|
6751
|
+
};
|
|
6707
6752
|
var ScriptSkill = class {
|
|
6708
6753
|
name;
|
|
6709
6754
|
description;
|
|
@@ -6836,7 +6881,7 @@ function scopeLlmKeys(scriptEnv, declaredProvider) {
|
|
|
6836
6881
|
}
|
|
6837
6882
|
return env;
|
|
6838
6883
|
}
|
|
6839
|
-
function buildCliSkill(parsed, entryPath, scriptEnv) {
|
|
6884
|
+
function buildCliSkill(parsed, entryPath, scriptEnv, network) {
|
|
6840
6885
|
let safeImageFile = parsed.imageFile;
|
|
6841
6886
|
if (safeImageFile !== void 0 && resolveInsidePathReal(entryPath, safeImageFile) === null) {
|
|
6842
6887
|
console.warn(
|
|
@@ -6924,6 +6969,35 @@ function buildCliSkill(parsed, entryPath, scriptEnv) {
|
|
|
6924
6969
|
}) : new StaticScriptSkill(scriptParams);
|
|
6925
6970
|
break;
|
|
6926
6971
|
}
|
|
6972
|
+
case "onchain": {
|
|
6973
|
+
if (parsed.script === void 0 || parsed.onchain === void 0) {
|
|
6974
|
+
throw new Error(
|
|
6975
|
+
`SKILL.md "${parsed.name}": internal error - script or onchain block missing for mode 'onchain'`
|
|
6976
|
+
);
|
|
6977
|
+
}
|
|
6978
|
+
const scriptPath = resolveInsidePathReal(entryPath, parsed.script);
|
|
6979
|
+
if (!scriptPath) {
|
|
6980
|
+
throw new Error(`SKILL.md "${parsed.name}": "script" must stay inside the skill directory`);
|
|
6981
|
+
}
|
|
6982
|
+
skill = new OnchainSkill({
|
|
6983
|
+
name: parsed.name,
|
|
6984
|
+
description: parsed.description,
|
|
6985
|
+
capabilities: parsed.capabilities,
|
|
6986
|
+
priceSubunits: Number(parsed.priceSubunits),
|
|
6987
|
+
asset: parsed.asset,
|
|
6988
|
+
scriptPath,
|
|
6989
|
+
scriptArgs: parsed.scriptArgs,
|
|
6990
|
+
scriptTimeoutMs: parsed.scriptTimeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS,
|
|
6991
|
+
scriptEnv: scopeLlmKeys(scriptEnv, parsed.llmOverride?.provider),
|
|
6992
|
+
image: parsed.image,
|
|
6993
|
+
imageFile: safeImageFile,
|
|
6994
|
+
dir: entryPath,
|
|
6995
|
+
llmOverride: parsed.llmOverride,
|
|
6996
|
+
onchain: parsed.onchain,
|
|
6997
|
+
network
|
|
6998
|
+
});
|
|
6999
|
+
break;
|
|
7000
|
+
}
|
|
6927
7001
|
case "x402": {
|
|
6928
7002
|
if (parsed.x402 === void 0) {
|
|
6929
7003
|
throw new Error(
|
|
@@ -6989,7 +7063,7 @@ function loadSkillsFromDir(skillsDir, options) {
|
|
|
6989
7063
|
warn: (_obj, msg) => console.warn(` ! ${msg ?? ""}`)
|
|
6990
7064
|
}
|
|
6991
7065
|
});
|
|
6992
|
-
skills.push(buildCliSkill(parsed, entryPath, options.scriptEnv));
|
|
7066
|
+
skills.push(buildCliSkill(parsed, entryPath, options.scriptEnv, options.network));
|
|
6993
7067
|
} catch (e) {
|
|
6994
7068
|
const message = e instanceof Error ? e.message : String(e);
|
|
6995
7069
|
console.warn(` ! Skipping skill "${entry}": ${message}`);
|
|
@@ -8368,6 +8442,12 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
8368
8442
|
agentName,
|
|
8369
8443
|
agentDescription: loaded.yaml.description ?? ""
|
|
8370
8444
|
};
|
|
8445
|
+
const onchainSkillCount = allSkills.filter((skill) => skill.onchain !== void 0).length;
|
|
8446
|
+
if (solanaAddress === void 0 && onchainSkillCount > 0) {
|
|
8447
|
+
console.warn(
|
|
8448
|
+
` ! ${onchainSkillCount} onchain capability(ies) declare a block but this agent has no Solana payment address, so the network their cards would promise is a guess. Add a payments entry to elisym.yaml.`
|
|
8449
|
+
);
|
|
8450
|
+
}
|
|
8371
8451
|
const x402Skills = allSkills.filter((skill) => skill.mode === "x402");
|
|
8372
8452
|
let x402InvariantBroken;
|
|
8373
8453
|
if (x402Skills.length > 0) {
|
|
@@ -8377,9 +8457,13 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
8377
8457
|
} else if (!solanaAddress) {
|
|
8378
8458
|
x402InvariantBroken = "no payments[] entry in elisym.yaml";
|
|
8379
8459
|
} else {
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8460
|
+
try {
|
|
8461
|
+
const bridgeSigner = await signerFromSecretKeyBase58(solanaSecretKey);
|
|
8462
|
+
if (bridgeSigner.address !== solanaAddress) {
|
|
8463
|
+
x402InvariantBroken = `payments[].address (${solanaAddress}) differs from the solana_secret_key address (${bridgeSigner.address})`;
|
|
8464
|
+
}
|
|
8465
|
+
} catch (error) {
|
|
8466
|
+
x402InvariantBroken = `solana_secret_key is present but unreadable - ${error instanceof Error ? error.message : String(error)}`;
|
|
8383
8467
|
}
|
|
8384
8468
|
}
|
|
8385
8469
|
for (const skill of x402Skills) {
|
|
@@ -8655,6 +8739,16 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
8655
8739
|
);
|
|
8656
8740
|
continue;
|
|
8657
8741
|
}
|
|
8742
|
+
if (withholdsOnchainCard(skill, solanaAddress)) {
|
|
8743
|
+
console.warn(
|
|
8744
|
+
` ! Not republishing "${skill.name}" - no Solana payments entry. An earlier card for it, if any, stays on the relays until it expires.`
|
|
8745
|
+
);
|
|
8746
|
+
logger.warn(
|
|
8747
|
+
{ event: "publish_skipped_onchain_no_wallet", kind: 31990, skill: skill.name },
|
|
8748
|
+
"capability not advertised - onchain block with no Solana payment address"
|
|
8749
|
+
);
|
|
8750
|
+
continue;
|
|
8751
|
+
}
|
|
8658
8752
|
try {
|
|
8659
8753
|
await client.discovery.publishCapability(identity2, buildCard(skill), kinds);
|
|
8660
8754
|
cardsPublished += 1;
|
|
@@ -8832,6 +8926,13 @@ function buildCapabilityCard(skill, inputs) {
|
|
|
8832
8926
|
// exists (delegatePubkey resolved). The pubkey is injected here, never
|
|
8833
8927
|
// taken from the SKILL.md - the operator declares only the cap/mechanism.
|
|
8834
8928
|
...skill.delegation && delegatePubkey ? { delegation: { ...skill.delegation, delegate_pubkey: delegatePubkey } } : {},
|
|
8929
|
+
// On-chain promise (`mode: onchain`): the network is stamped from the
|
|
8930
|
+
// agent's wallet here, never from SKILL.md, so a capability copied between
|
|
8931
|
+
// a devnet and a mainnet agent cannot advertise the wrong chain.
|
|
8932
|
+
// Only stamped when the agent actually has a Solana payment entry: without
|
|
8933
|
+
// one `walletNetwork` is a default, and a card must never promise a chain
|
|
8934
|
+
// the operator never chose. `cmdStart` warns for such a skill at step 7a.
|
|
8935
|
+
...skill.onchain && solanaAddress ? { onchain: { ...skill.onchain, network: walletNetwork } } : {},
|
|
8835
8936
|
payment: solanaAddress ? {
|
|
8836
8937
|
chain: "solana",
|
|
8837
8938
|
network: walletNetwork,
|
|
@@ -8844,6 +8945,9 @@ function buildCapabilityCard(skill, inputs) {
|
|
|
8844
8945
|
} : void 0
|
|
8845
8946
|
};
|
|
8846
8947
|
}
|
|
8948
|
+
function withholdsOnchainCard(skill, solanaAddress) {
|
|
8949
|
+
return skill.onchain !== void 0 && solanaAddress === void 0;
|
|
8950
|
+
}
|
|
8847
8951
|
function buildScriptEnv(secrets) {
|
|
8848
8952
|
const scriptEnv = { ...process.env };
|
|
8849
8953
|
delete scriptEnv.ELISYM_PASSPHRASE;
|