@elisym/cli 0.21.2 → 0.22.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 +70 -38
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --no-deprecation
|
|
2
2
|
import { ReadableStream } from 'node:stream/web';
|
|
3
3
|
import { readFileSync, existsSync, readdirSync, statSync, renameSync, chmodSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { dirname, join, resolve, basename, relative, sep } from 'node:path';
|
|
5
|
-
import { SolanaPaymentStrategy, validateAgentName, RELAYS, ElisymIdentity, formatSol, formatAssetAmount, USDC_SOLANA_DEVNET, ElisymClient,
|
|
4
|
+
import { dirname, join, resolve, basename, relative, sep, extname } from 'node:path';
|
|
5
|
+
import { SolanaPaymentStrategy, validateAgentName, RELAYS, ElisymIdentity, formatSol, formatAssetAmount, USDC_SOLANA_DEVNET, ElisymClient, POLICY_D_TAG_PREFIX, KIND_LONG_FORM_ARTICLE, jobRequestKind, DEFAULT_KIND_OFFSET, toDTag, DEFAULTS, makeCensor, DEFAULT_REDACT_PATHS, POLICY_T_TAG, createSlidingWindowLimiter, getProtocolProgramId, getProtocolConfig, utf8ByteLength, LIMITS, calculateProtocolFee, decodeJobPayload, BoundedSet, KIND_JOB_FEEDBACK, NATIVE_SOL } from '@elisym/sdk';
|
|
6
6
|
import { ElisymYamlSchema, resolveInHome, resolveInProject, createAgentDir, writeYamlInitial, writeExampleSkillTemplate, writeSecrets, listAgents, loadAgent, writeYaml, agentPaths, readMediaCache, loadPoliciesFromDir, ensureGitignoreHasIrohEntry, lookupCachedUrl, newCacheEntry, writeMediaCache } from '@elisym/sdk/agent-store';
|
|
7
7
|
import { isAddress, createSolanaRpc, address } from '@solana/kit';
|
|
8
8
|
import { generateSecretKey, getPublicKey, nip19, verifyEvent } from 'nostr-tools';
|
|
@@ -2051,6 +2051,18 @@ function createLogger(options = {}) {
|
|
|
2051
2051
|
bannerLog: logWithIndent
|
|
2052
2052
|
};
|
|
2053
2053
|
}
|
|
2054
|
+
var MIME_BY_EXT = {
|
|
2055
|
+
".png": "image/png",
|
|
2056
|
+
".jpg": "image/jpeg",
|
|
2057
|
+
".jpeg": "image/jpeg",
|
|
2058
|
+
".gif": "image/gif",
|
|
2059
|
+
".webp": "image/webp",
|
|
2060
|
+
".svg": "image/svg+xml",
|
|
2061
|
+
".avif": "image/avif"
|
|
2062
|
+
};
|
|
2063
|
+
function mimeFromPath(path) {
|
|
2064
|
+
return MIME_BY_EXT[extname(path).toLowerCase()] ?? "application/octet-stream";
|
|
2065
|
+
}
|
|
2054
2066
|
var payment = new SolanaPaymentStrategy();
|
|
2055
2067
|
var LEDGER_GC_INTERVAL_MS = 60 * 60 * 1e3;
|
|
2056
2068
|
var LEDGER_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -4163,14 +4175,13 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
4163
4175
|
}
|
|
4164
4176
|
}
|
|
4165
4177
|
}
|
|
4166
|
-
const media = new MediaService();
|
|
4167
4178
|
const mediaCache = await readMediaCache(loaded.dir);
|
|
4168
4179
|
let mediaCacheDirty = false;
|
|
4169
4180
|
const pictureUrl = await resolveMediaField(
|
|
4170
4181
|
loaded.yaml.picture,
|
|
4171
4182
|
loaded.dir,
|
|
4172
4183
|
mediaCache,
|
|
4173
|
-
|
|
4184
|
+
client.blossom,
|
|
4174
4185
|
identity,
|
|
4175
4186
|
(updated) => mediaCacheDirty = mediaCacheDirty || updated
|
|
4176
4187
|
);
|
|
@@ -4178,7 +4189,7 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
4178
4189
|
loaded.yaml.banner,
|
|
4179
4190
|
loaded.dir,
|
|
4180
4191
|
mediaCache,
|
|
4181
|
-
|
|
4192
|
+
client.blossom,
|
|
4182
4193
|
identity,
|
|
4183
4194
|
(updated) => mediaCacheDirty = mediaCacheDirty || updated
|
|
4184
4195
|
);
|
|
@@ -4194,7 +4205,7 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
4194
4205
|
cacheKey,
|
|
4195
4206
|
absPath,
|
|
4196
4207
|
mediaCache,
|
|
4197
|
-
|
|
4208
|
+
client.blossom,
|
|
4198
4209
|
identity,
|
|
4199
4210
|
() => mediaCacheDirty = true
|
|
4200
4211
|
);
|
|
@@ -4224,7 +4235,36 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
4224
4235
|
const localPolicyDTags = new Set(
|
|
4225
4236
|
policies.map((policy) => `${POLICY_D_TAG_PREFIX}${policy.type}`)
|
|
4226
4237
|
);
|
|
4238
|
+
async function fetchPublishedPolicies() {
|
|
4239
|
+
try {
|
|
4240
|
+
return await client.pool.querySync({
|
|
4241
|
+
kinds: [KIND_LONG_FORM_ARTICLE],
|
|
4242
|
+
authors: [identity.publicKey],
|
|
4243
|
+
"#t": [POLICY_T_TAG]
|
|
4244
|
+
});
|
|
4245
|
+
} catch {
|
|
4246
|
+
return [];
|
|
4247
|
+
}
|
|
4248
|
+
}
|
|
4249
|
+
const publishedPolicies = await fetchPublishedPolicies();
|
|
4250
|
+
const latestPolicyByDTag = /* @__PURE__ */ new Map();
|
|
4251
|
+
for (const event of publishedPolicies) {
|
|
4252
|
+
const dTag = event.tags.find((tag) => tag[0] === "d")?.[1];
|
|
4253
|
+
if (!dTag) {
|
|
4254
|
+
continue;
|
|
4255
|
+
}
|
|
4256
|
+
const prev = latestPolicyByDTag.get(dTag);
|
|
4257
|
+
if (!prev || event.created_at > prev.created_at) {
|
|
4258
|
+
latestPolicyByDTag.set(dTag, event);
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4227
4261
|
for (const policy of policies) {
|
|
4262
|
+
const onRelay = latestPolicyByDTag.get(`${POLICY_D_TAG_PREFIX}${policy.type}`);
|
|
4263
|
+
const relayVersion = onRelay?.tags.find((tag) => tag[0] === "policy_version")?.[1];
|
|
4264
|
+
if (onRelay && onRelay.content && relayVersion === policy.version && onRelay.content === policy.content) {
|
|
4265
|
+
console.log(` * Policy: ${policy.type}@${policy.version} (unchanged, skipped)`);
|
|
4266
|
+
continue;
|
|
4267
|
+
}
|
|
4228
4268
|
try {
|
|
4229
4269
|
const { naddr } = await client.policies.publishPolicy(identity, policy);
|
|
4230
4270
|
console.log(` * Policy: ${policy.type}@${policy.version} -> ${naddr}`);
|
|
@@ -4245,31 +4285,23 @@ async function cmdStart(nameArg, options = {}) {
|
|
|
4245
4285
|
);
|
|
4246
4286
|
}
|
|
4247
4287
|
}
|
|
4248
|
-
|
|
4249
|
-
const
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
continue;
|
|
4265
|
-
}
|
|
4266
|
-
try {
|
|
4267
|
-
await client.policies.deletePolicy(identity, type);
|
|
4268
|
-
console.log(` Removed stale policy: ${type}`);
|
|
4269
|
-
} catch {
|
|
4270
|
-
}
|
|
4288
|
+
for (const event of publishedPolicies) {
|
|
4289
|
+
const dTag = event.tags.find((tag) => tag[0] === "d")?.[1];
|
|
4290
|
+
if (!dTag || localPolicyDTags.has(dTag)) {
|
|
4291
|
+
continue;
|
|
4292
|
+
}
|
|
4293
|
+
if (!event.content) {
|
|
4294
|
+
continue;
|
|
4295
|
+
}
|
|
4296
|
+
const type = event.tags.find((tag) => tag[0] === "policy_type")?.[1];
|
|
4297
|
+
if (!type) {
|
|
4298
|
+
continue;
|
|
4299
|
+
}
|
|
4300
|
+
try {
|
|
4301
|
+
await client.policies.deletePolicy(identity, type);
|
|
4302
|
+
console.log(` Removed stale policy: ${type}`);
|
|
4303
|
+
} catch {
|
|
4271
4304
|
}
|
|
4272
|
-
} catch {
|
|
4273
4305
|
}
|
|
4274
4306
|
const kinds = [jobRequestKind(DEFAULT_KIND_OFFSET)];
|
|
4275
4307
|
function buildCard(skill) {
|
|
@@ -4469,7 +4501,7 @@ function stripRpcSecrets(raw) {
|
|
|
4469
4501
|
return "[unparseable RPC URL]";
|
|
4470
4502
|
}
|
|
4471
4503
|
}
|
|
4472
|
-
async function resolveMediaField(value, agentDir, cache,
|
|
4504
|
+
async function resolveMediaField(value, agentDir, cache, blossom, identity, onCacheUpdate) {
|
|
4473
4505
|
if (!value) {
|
|
4474
4506
|
return void 0;
|
|
4475
4507
|
}
|
|
@@ -4481,7 +4513,7 @@ async function resolveMediaField(value, agentDir, cache, media, identity, onCach
|
|
|
4481
4513
|
console.warn(` ! Skipping media field "${value}": path must stay inside the agent directory.`);
|
|
4482
4514
|
return void 0;
|
|
4483
4515
|
}
|
|
4484
|
-
return uploadOrReuse(value, absPath, cache,
|
|
4516
|
+
return uploadOrReuse(value, absPath, cache, blossom, identity, () => onCacheUpdate(true));
|
|
4485
4517
|
}
|
|
4486
4518
|
function resolveInsideAgentDir(value, agentDir) {
|
|
4487
4519
|
const agentRoot = resolve(agentDir);
|
|
@@ -4492,7 +4524,7 @@ function resolveInsideAgentDir(value, agentDir) {
|
|
|
4492
4524
|
}
|
|
4493
4525
|
return candidate;
|
|
4494
4526
|
}
|
|
4495
|
-
async function uploadOrReuse(cacheKey, absPath, cache,
|
|
4527
|
+
async function uploadOrReuse(cacheKey, absPath, cache, blossom, identity, onCacheUpdate) {
|
|
4496
4528
|
try {
|
|
4497
4529
|
const cached = await lookupCachedUrl(cache, cacheKey, absPath);
|
|
4498
4530
|
if (cached) {
|
|
@@ -4501,12 +4533,12 @@ async function uploadOrReuse(cacheKey, absPath, cache, media, identity, onCacheU
|
|
|
4501
4533
|
console.log(` Uploading ${basename(absPath)}...`);
|
|
4502
4534
|
const data = readFileSync(absPath);
|
|
4503
4535
|
const sha256 = createHash("sha256").update(data).digest("hex");
|
|
4504
|
-
const blob = new Blob([data]);
|
|
4505
|
-
const
|
|
4506
|
-
cache[cacheKey] = newCacheEntry(url, sha256);
|
|
4536
|
+
const blob = new Blob([data], { type: mimeFromPath(absPath) });
|
|
4537
|
+
const descriptor = await blossom.upload(identity, blob);
|
|
4538
|
+
cache[cacheKey] = newCacheEntry(descriptor.url, sha256);
|
|
4507
4539
|
onCacheUpdate();
|
|
4508
|
-
console.log(` Uploaded: ${url}`);
|
|
4509
|
-
return url;
|
|
4540
|
+
console.log(` Uploaded: ${descriptor.url}`);
|
|
4541
|
+
return descriptor.url;
|
|
4510
4542
|
} catch (e) {
|
|
4511
4543
|
console.warn(` ! Failed to upload ${basename(absPath)}: ${e.message}`);
|
|
4512
4544
|
return void 0;
|