@yamo/cli 1.3.13 → 1.3.14
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 +62 -1
- package/dist/commands/audit.js +67 -0
- package/dist/commands/bridge.js +116 -0
- package/dist/commands/config.js +74 -0
- package/dist/commands/download-bundle.js +87 -0
- package/dist/commands/hash.js +29 -0
- package/dist/commands/init.js +38 -0
- package/dist/commands/submit.js +174 -0
- package/dist/index.js +57 -322
- package/dist/interfaces.js +2 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/config.js +67 -0
- package/dist/utils/constants.js +13 -0
- package/dist/utils/format.js +43 -0
- package/dist/utils/spinner.js +38 -0
- package/dist/utils/storage.js +69 -0
- package/dist/utils/validation.js +39 -0
- package/package.json +22 -6
package/dist/index.js
CHANGED
|
@@ -1,337 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
-
};
|
|
39
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
4
|
const commander_1 = require("commander");
|
|
41
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
43
|
-
const fs_1 = __importDefault(require("fs"));
|
|
44
|
-
const path_1 = __importDefault(require("path"));
|
|
45
|
-
const dotenv = __importStar(require("dotenv"));
|
|
46
5
|
const core_1 = require("@yamo/core");
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
DEFAULT_INTENT: "execute_task",
|
|
57
|
-
HEX_PREFIX: "0x",
|
|
58
|
-
HASH_ALGORITHM: "sha256",
|
|
59
|
-
};
|
|
6
|
+
const config_js_1 = require("./utils/config.js");
|
|
7
|
+
const constants_js_1 = require("./utils/constants.js");
|
|
8
|
+
const hash_js_1 = require("./commands/hash.js");
|
|
9
|
+
const init_js_1 = require("./commands/init.js");
|
|
10
|
+
const submit_js_1 = require("./commands/submit.js");
|
|
11
|
+
const audit_js_1 = require("./commands/audit.js");
|
|
12
|
+
const download_bundle_js_1 = require("./commands/download-bundle.js");
|
|
13
|
+
const config_js_2 = require("./commands/config.js");
|
|
14
|
+
const bridge_js_1 = require("./commands/bridge.js");
|
|
60
15
|
const program = new commander_1.Command();
|
|
61
|
-
const ipfsManager = new core_1.IpfsManager();
|
|
62
|
-
const chainClient = new core_1.YamoChainClient();
|
|
63
|
-
// Hash utilities
|
|
64
|
-
const hash = {
|
|
65
|
-
sha256: (content) => {
|
|
66
|
-
return crypto_1.default.createHash(CONSTANTS.HASH_ALGORITHM).update(content).digest("hex");
|
|
67
|
-
},
|
|
68
|
-
bytes32: (content) => {
|
|
69
|
-
return `${CONSTANTS.HEX_PREFIX}${hash.sha256(content)}`;
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
// Response formatting helpers
|
|
73
|
-
const format = {
|
|
74
|
-
success: (msg) => console.log(chalk_1.default.green(msg)),
|
|
75
|
-
error: (msg) => console.error(chalk_1.default.red(`Error: ${msg}`)),
|
|
76
|
-
info: (msg) => console.log(chalk_1.default.blue(msg)),
|
|
77
|
-
warn: (msg) => console.log(chalk_1.default.yellow(msg)),
|
|
78
|
-
detail: (msg) => console.log(chalk_1.default.gray(msg)),
|
|
79
|
-
value: (msg) => console.log(chalk_1.default.cyan(msg)),
|
|
80
|
-
};
|
|
81
|
-
// Error handling helper
|
|
82
|
-
function handleCommandError(error, context) {
|
|
83
|
-
if (error instanceof Error) {
|
|
84
|
-
const message = context ? `${context}: ${error.message}` : error.message;
|
|
85
|
-
format.error(message);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
format.error("Unknown error occurred");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// Validation helpers
|
|
92
|
-
function validateBytes32(value, fieldName) {
|
|
93
|
-
if (!value.match(CONSTANTS.HASH_PATTERN)) {
|
|
94
|
-
throw new Error(`${fieldName} must be a valid bytes32 hash (0x + 64 hex chars). ` +
|
|
95
|
-
`Received: ${value.substring(0, 20)}...` +
|
|
96
|
-
`\nDo NOT include algorithm prefixes like "sha256:"`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function validateBlockId(blockId) {
|
|
100
|
-
if (!blockId)
|
|
101
|
-
throw new Error("blockId is required");
|
|
102
|
-
const parts = blockId.split('_');
|
|
103
|
-
if (parts.length < 2) {
|
|
104
|
-
throw new Error(`blockId must follow format {origin}_{workflow} (e.g., 'claude_chain'). Received: ${blockId}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
// Submit command helpers
|
|
108
|
-
async function validateEncryptionKey(key) {
|
|
109
|
-
const { validatePasswordStrength } = await import("@yamo/core");
|
|
110
|
-
try {
|
|
111
|
-
validatePasswordStrength(key);
|
|
112
|
-
}
|
|
113
|
-
catch (e) {
|
|
114
|
-
format.error("Password validation failed:");
|
|
115
|
-
format.error(e.message);
|
|
116
|
-
format.warn("\nKey requirements:");
|
|
117
|
-
console.error(" • Minimum 12 characters");
|
|
118
|
-
console.error(" • Mix of uppercase, lowercase, numbers, symbols");
|
|
119
|
-
console.error(" • Avoid common patterns (password, 123456, qwerty)");
|
|
120
|
-
throw e;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
function prepareIpfsFiles(content, file) {
|
|
124
|
-
const files = [{ name: CONSTANTS.DEFAULT_FILENAME, content }];
|
|
125
|
-
const outputMatch = content.match(/output:\s*([^;]+);/);
|
|
126
|
-
if (outputMatch) {
|
|
127
|
-
const artifactName = outputMatch[1].trim();
|
|
128
|
-
// Security: Check for path traversal patterns
|
|
129
|
-
if (artifactName.includes('..') || artifactName.startsWith('/')) {
|
|
130
|
-
throw new Error(`Invalid artifact name: ${artifactName} (path-like names are not allowed)`);
|
|
131
|
-
}
|
|
132
|
-
const artifactPath = path_1.default.join(path_1.default.dirname(file), artifactName);
|
|
133
|
-
const resolvedPath = path_1.default.resolve(artifactPath);
|
|
134
|
-
const inputDir = path_1.default.resolve(path_1.default.dirname(file));
|
|
135
|
-
if (!resolvedPath.startsWith(inputDir)) {
|
|
136
|
-
throw new Error(`Artifact path outside allowed directory: ${artifactName}`);
|
|
137
|
-
}
|
|
138
|
-
if (fs_1.default.existsSync(resolvedPath)) {
|
|
139
|
-
format.info(`Bundling output: ${artifactName}`);
|
|
140
|
-
files.push({ name: artifactName, content: fs_1.default.readFileSync(resolvedPath, "utf8") });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return files;
|
|
144
|
-
}
|
|
145
|
-
async function resolvePreviousBlock(prev) {
|
|
146
|
-
if (prev) {
|
|
147
|
-
validateBytes32(prev, "previousBlock");
|
|
148
|
-
return prev;
|
|
149
|
-
}
|
|
150
|
-
format.info("[INFO] No previousBlock provided, fetching latest block from chain...");
|
|
151
|
-
const latestHash = await chainClient.getLatestBlockHash();
|
|
152
|
-
if (latestHash && latestHash !== CONSTANTS.GENESIS_HASH) {
|
|
153
|
-
format.success(`[INFO] Using latest block's contentHash: ${latestHash}`);
|
|
154
|
-
return latestHash;
|
|
155
|
-
}
|
|
156
|
-
format.warn("[INFO] No existing blocks found, using genesis");
|
|
157
|
-
return CONSTANTS.GENESIS_HASH;
|
|
158
|
-
}
|
|
159
16
|
program
|
|
160
|
-
.name(
|
|
161
|
-
.description(
|
|
162
|
-
.version(
|
|
17
|
+
.name('yamo')
|
|
18
|
+
.description('YAMO CLI - Blockchain-anchored agent workflow system')
|
|
19
|
+
.version('1.3.14');
|
|
163
20
|
program
|
|
164
|
-
.command(
|
|
165
|
-
.description(
|
|
166
|
-
.argument(
|
|
167
|
-
.action(
|
|
168
|
-
try {
|
|
169
|
-
const content = fs_1.default.readFileSync(file, "utf8").trim();
|
|
170
|
-
const contentHash = hash.bytes32(content);
|
|
171
|
-
format.success("Block Content Hash:");
|
|
172
|
-
format.value(contentHash);
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
handleCommandError(error);
|
|
176
|
-
}
|
|
177
|
-
});
|
|
21
|
+
.command('hash')
|
|
22
|
+
.description('Calculate SHA256 hash of a file')
|
|
23
|
+
.argument('<file>', 'Path to the file')
|
|
24
|
+
.action(hash_js_1.hashCommand);
|
|
178
25
|
program
|
|
179
|
-
.command(
|
|
180
|
-
.description(
|
|
181
|
-
.argument(
|
|
182
|
-
.option(
|
|
183
|
-
.action(
|
|
184
|
-
try {
|
|
185
|
-
const template = `
|
|
186
|
-
agent: ${agent_name};
|
|
187
|
-
intent: ${options.intent};
|
|
188
|
-
context:
|
|
189
|
-
platform;yamo_v0.5;
|
|
190
|
-
constraints:
|
|
191
|
-
- human_readable;true;
|
|
192
|
-
priority: medium;
|
|
193
|
-
output: result.json;
|
|
194
|
-
meta: hypothesis;Initial hypothesis;
|
|
195
|
-
meta: confidence;0.9;
|
|
196
|
-
log: session_start;timestamp;${new Date().toISOString()};
|
|
197
|
-
handoff: User;
|
|
198
|
-
`.trim();
|
|
199
|
-
fs_1.default.writeFileSync(CONSTANTS.DEFAULT_FILENAME, template);
|
|
200
|
-
format.success(`Created YAMO template: ${chalk_1.default.bold(CONSTANTS.DEFAULT_FILENAME)}`);
|
|
201
|
-
}
|
|
202
|
-
catch (error) {
|
|
203
|
-
handleCommandError(error);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
26
|
+
.command('init')
|
|
27
|
+
.description('Create a new YAMO block template')
|
|
28
|
+
.argument('<agent_name>', 'Name of the agent')
|
|
29
|
+
.option('--intent <intent>', 'Intent description', constants_js_1.CONSTANTS.DEFAULT_INTENT)
|
|
30
|
+
.action(init_js_1.initCommand);
|
|
206
31
|
program
|
|
207
|
-
.command(
|
|
208
|
-
.description(
|
|
209
|
-
.argument(
|
|
210
|
-
.
|
|
211
|
-
.option(
|
|
212
|
-
.option(
|
|
213
|
-
.option(
|
|
214
|
-
.option(
|
|
215
|
-
.option(
|
|
216
|
-
.option(
|
|
217
|
-
.action(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// Validate encryption key if needed
|
|
222
|
-
if (options.encrypt) {
|
|
223
|
-
const key = options.key || process.env.YAMO_ENCRYPTION_KEY;
|
|
224
|
-
if (!key) {
|
|
225
|
-
throw new Error("Encryption enabled but no key provided. Use --key or set YAMO_ENCRYPTION_KEY");
|
|
226
|
-
}
|
|
227
|
-
await validateEncryptionKey(key);
|
|
228
|
-
}
|
|
229
|
-
// Calculate content hash
|
|
230
|
-
const content = fs_1.default.readFileSync(file, "utf8").trim();
|
|
231
|
-
const contentHash = hash.bytes32(content);
|
|
232
|
-
format.info(`Calculated Hash: ${contentHash}`);
|
|
233
|
-
// Handle IPFS upload
|
|
234
|
-
let ipfsCID;
|
|
235
|
-
if (options.ipfs) {
|
|
236
|
-
const files = prepareIpfsFiles(content, file);
|
|
237
|
-
const encryptionKey = options.encrypt
|
|
238
|
-
? (options.key || process.env.YAMO_ENCRYPTION_KEY)
|
|
239
|
-
: undefined;
|
|
240
|
-
if (encryptionKey) {
|
|
241
|
-
format.warn("🔒 Encrypting bundle...");
|
|
242
|
-
}
|
|
243
|
-
ipfsCID = await ipfsManager.upload({ content, files, encryptionKey });
|
|
244
|
-
format.info(`IPFS Bundle CID: ${ipfsCID}`);
|
|
245
|
-
}
|
|
246
|
-
// Resolve previous block
|
|
247
|
-
const resolvedPreviousBlock = await resolvePreviousBlock(options.prev);
|
|
248
|
-
// Submit to blockchain
|
|
249
|
-
await chainClient.submitBlock(options.id, resolvedPreviousBlock, contentHash, options.consensus, options.ledger, ipfsCID);
|
|
250
|
-
}
|
|
251
|
-
catch (error) {
|
|
252
|
-
handleCommandError(error);
|
|
253
|
-
}
|
|
32
|
+
.command('submit')
|
|
33
|
+
.description('Submit a YAMO block to the blockchain')
|
|
34
|
+
.argument('<file>', 'Path to the YAMO file')
|
|
35
|
+
.option('--id <blockId>', 'Unique Block ID (format: {origin}_{workflow})')
|
|
36
|
+
.option('--prev <previousBlock>', 'Previous block hash (auto-fetches if omitted)')
|
|
37
|
+
.option('--consensus <type>', 'Consensus mechanism', constants_js_1.CONSTANTS.DEFAULT_CONSENSUS)
|
|
38
|
+
.option('--ledger <name>', 'Ledger name', constants_js_1.CONSTANTS.DEFAULT_LEDGER)
|
|
39
|
+
.option('--ipfs', 'Upload content to IPFS', false)
|
|
40
|
+
.option('-e, --encrypt', 'Encrypt bundle before IPFS upload', false)
|
|
41
|
+
.option('-k, --key <key>', 'Encryption/decryption key')
|
|
42
|
+
.action((file, options) => {
|
|
43
|
+
const chainClient = new core_1.YamoChainClient(config_js_1.config.rpcUrl, config_js_1.config.privateKey, config_js_1.config.contractAddress);
|
|
44
|
+
const ipfsClient = new core_1.IpfsManager({ jwt: config_js_1.config.pinataJwt });
|
|
45
|
+
return (0, submit_js_1.submitCommand)(file, options, { chainClient, ipfsClient });
|
|
254
46
|
});
|
|
255
47
|
program
|
|
256
|
-
.command(
|
|
257
|
-
.description(
|
|
258
|
-
.argument(
|
|
259
|
-
.option(
|
|
260
|
-
.action(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (!block) {
|
|
265
|
-
format.error("Block not found on-chain.");
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
format.detail("Found on-chain record:");
|
|
269
|
-
console.log(` Agent: ${block.agentAddress}`);
|
|
270
|
-
console.log(` Hash: ${block.contentHash}`);
|
|
271
|
-
console.log(` IPFS: ${block.ipfsCID || "None"}`);
|
|
272
|
-
if (!block.ipfsCID) {
|
|
273
|
-
format.warn("⚠️ No IPFS CID. Cannot perform deep content audit.");
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
format.info("Fetching content from IPFS...");
|
|
277
|
-
const key = options.key || process.env.YAMO_ENCRYPTION_KEY;
|
|
278
|
-
const content = await ipfsManager.download(block.ipfsCID, key);
|
|
279
|
-
const calcHash = hash.bytes32(content);
|
|
280
|
-
console.log(` Calculated: ${calcHash}`);
|
|
281
|
-
if (calcHash === block.contentHash) {
|
|
282
|
-
format.success("✅ INTEGRITY VERIFIED: Content matches chain hash.");
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
format.error("❌ INTEGRITY FAILED: Hash mismatch!");
|
|
286
|
-
console.log(` Expected: ${block.contentHash}`);
|
|
287
|
-
console.log(` Got: ${calcHash}`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
catch (error) {
|
|
291
|
-
handleCommandError(error);
|
|
292
|
-
}
|
|
48
|
+
.command('audit')
|
|
49
|
+
.description('Verify a block on the blockchain')
|
|
50
|
+
.argument('<blockId>', 'Block ID to audit')
|
|
51
|
+
.option('-k, --key <key>', 'Decryption key')
|
|
52
|
+
.action((blockId, options) => {
|
|
53
|
+
const chainClient = new core_1.YamoChainClient(config_js_1.config.rpcUrl, config_js_1.config.privateKey, config_js_1.config.contractAddress);
|
|
54
|
+
const ipfsClient = new core_1.IpfsManager({ jwt: config_js_1.config.pinataJwt });
|
|
55
|
+
return (0, audit_js_1.auditCommand)(blockId, options, { chainClient, ipfsClient });
|
|
293
56
|
});
|
|
294
57
|
program
|
|
295
|
-
.command(
|
|
296
|
-
.description(
|
|
297
|
-
.argument(
|
|
298
|
-
.
|
|
299
|
-
.
|
|
300
|
-
.action(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (!fs_1.default.existsSync(outputDir)) {
|
|
310
|
-
fs_1.default.mkdirSync(outputDir, { recursive: true });
|
|
311
|
-
}
|
|
312
|
-
// Write block.yamo
|
|
313
|
-
fs_1.default.writeFileSync(path_1.default.join(outputDir, CONSTANTS.DEFAULT_FILENAME), bundle.block);
|
|
314
|
-
format.success(`✓ Downloaded ${CONSTANTS.DEFAULT_FILENAME}`);
|
|
315
|
-
// Write metadata
|
|
316
|
-
if (bundle.metadata) {
|
|
317
|
-
fs_1.default.writeFileSync(path_1.default.join(outputDir, "metadata.json"), JSON.stringify(bundle.metadata, null, 2));
|
|
318
|
-
format.success("✓ Downloaded metadata.json");
|
|
319
|
-
}
|
|
320
|
-
// Write artifact files
|
|
321
|
-
for (const [filename, content] of Object.entries(bundle.files)) {
|
|
322
|
-
const filePath = path_1.default.join(outputDir, filename);
|
|
323
|
-
fs_1.default.writeFileSync(filePath, content);
|
|
324
|
-
format.success(`✓ Downloaded ${filename}`);
|
|
325
|
-
}
|
|
326
|
-
format.success(`\nBundle saved to: ${outputDir}`);
|
|
327
|
-
format.detail(`Files: ${1 + Object.keys(bundle.files).length} total`);
|
|
328
|
-
if (bundle.metadata?.hasEncryption) {
|
|
329
|
-
format.warn("🔒 Bundle was decrypted using provided key");
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
catch (error) {
|
|
333
|
-
handleCommandError(error);
|
|
334
|
-
format.detail("\nIf the bundle is encrypted, provide --key or set YAMO_ENCRYPTION_KEY");
|
|
335
|
-
}
|
|
336
|
-
});
|
|
58
|
+
.command('config')
|
|
59
|
+
.description('Manage local configuration and secrets')
|
|
60
|
+
.argument('<action>', 'Action: set, get, list, remove')
|
|
61
|
+
.argument('[key]', 'Configuration key')
|
|
62
|
+
.argument('[value]', 'Configuration value')
|
|
63
|
+
.action(config_js_2.configCommand);
|
|
64
|
+
program
|
|
65
|
+
.command('download-bundle')
|
|
66
|
+
.description('Download bundle from IPFS')
|
|
67
|
+
.argument('<cid>', 'IPFS content identifier')
|
|
68
|
+
.requiredOption('-o, --output <path>', 'Output file path')
|
|
69
|
+
.option('-k, --key <key>', 'Decryption key')
|
|
70
|
+
.action(download_bundle_js_1.downloadBundleCommand);
|
|
71
|
+
program.addCommand((0, bridge_js_1.bridgeCommand)());
|
|
337
72
|
program.parse();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.validateConfig = exports.config = void 0;
|
|
37
|
+
const dotenv = __importStar(require("dotenv"));
|
|
38
|
+
const storage_js_1 = require("./storage.js");
|
|
39
|
+
// Load environment variables
|
|
40
|
+
dotenv.config();
|
|
41
|
+
/**
|
|
42
|
+
* Centralized configuration for YAMO CLI.
|
|
43
|
+
* Loads and types environment variables with local storage fallback.
|
|
44
|
+
*/
|
|
45
|
+
exports.config = {
|
|
46
|
+
rpcUrl: process.env.RPC_URL || storage_js_1.storage.get('RPC_URL') || 'http://127.0.0.1:8545',
|
|
47
|
+
privateKey: process.env.PRIVATE_KEY || storage_js_1.storage.get('PRIVATE_KEY'),
|
|
48
|
+
contractAddress: process.env.CONTRACT_ADDRESS || storage_js_1.storage.get('CONTRACT_ADDRESS'),
|
|
49
|
+
encryptionKey: process.env.YAMO_ENCRYPTION_KEY || storage_js_1.storage.get('YAMO_ENCRYPTION_KEY'),
|
|
50
|
+
pinataJwt: process.env.PINATA_JWT || storage_js_1.storage.get('PINATA_JWT'),
|
|
51
|
+
bridgeUrl: process.env.YAMO_BRIDGE_URL || storage_js_1.storage.get('YAMO_BRIDGE_URL'),
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Validates that required configuration is present for specific operations.
|
|
55
|
+
*/
|
|
56
|
+
exports.validateConfig = {
|
|
57
|
+
/**
|
|
58
|
+
* Ensure encryption key is available
|
|
59
|
+
*/
|
|
60
|
+
requireEncryptionKey: (providedKey) => {
|
|
61
|
+
const key = providedKey || exports.config.encryptionKey;
|
|
62
|
+
if (!key) {
|
|
63
|
+
throw new Error('Encryption enabled but no key provided. Use --key or set YAMO_ENCRYPTION_KEY');
|
|
64
|
+
}
|
|
65
|
+
return key;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CONSTANTS = void 0;
|
|
4
|
+
exports.CONSTANTS = {
|
|
5
|
+
HASH_PATTERN: /^0x[a-fA-F0-9]{64}$/,
|
|
6
|
+
GENESIS_HASH: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
7
|
+
DEFAULT_FILENAME: 'block.yamo',
|
|
8
|
+
DEFAULT_CONSENSUS: 'cli_manual',
|
|
9
|
+
DEFAULT_LEDGER: 'yamo_cli',
|
|
10
|
+
DEFAULT_INTENT: 'execute_task',
|
|
11
|
+
HEX_PREFIX: '0x',
|
|
12
|
+
HASH_ALGORITHM: 'sha256',
|
|
13
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.format = void 0;
|
|
7
|
+
exports.handleCommandError = handleCommandError;
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
exports.format = {
|
|
10
|
+
success(msg) {
|
|
11
|
+
console.log(chalk_1.default.green(msg));
|
|
12
|
+
},
|
|
13
|
+
error(msg) {
|
|
14
|
+
console.error(chalk_1.default.red(`[ERROR] ${msg}`));
|
|
15
|
+
},
|
|
16
|
+
info(msg) {
|
|
17
|
+
console.log(chalk_1.default.blue(msg));
|
|
18
|
+
},
|
|
19
|
+
warn(msg) {
|
|
20
|
+
console.error(chalk_1.default.yellow(`[WARN] ${msg}`));
|
|
21
|
+
},
|
|
22
|
+
detail(msg) {
|
|
23
|
+
console.log(chalk_1.default.gray(msg));
|
|
24
|
+
},
|
|
25
|
+
value(msg) {
|
|
26
|
+
console.log(chalk_1.default.cyan(msg));
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Handles command errors with consistent formatting.
|
|
31
|
+
* @param error - Error object or unknown value
|
|
32
|
+
* @param context - Optional context message
|
|
33
|
+
*/
|
|
34
|
+
function handleCommandError(error, context) {
|
|
35
|
+
if (error instanceof Error) {
|
|
36
|
+
const message = context ? `${context}: ${error.message}` : error.message;
|
|
37
|
+
exports.format.error(message);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
exports.format.error('Unknown error occurred');
|
|
41
|
+
}
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createSpinner = createSpinner;
|
|
7
|
+
exports.withSpinner = withSpinner;
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
/**
|
|
10
|
+
* Creates and starts a professional, emoji-free spinner.
|
|
11
|
+
* @param text - The text to display with the spinner
|
|
12
|
+
* @returns The spinner instance
|
|
13
|
+
*/
|
|
14
|
+
function createSpinner(text) {
|
|
15
|
+
return (0, ora_1.default)({
|
|
16
|
+
text,
|
|
17
|
+
color: 'blue',
|
|
18
|
+
spinner: 'dots',
|
|
19
|
+
}).start();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Wraps a promise with a spinner.
|
|
23
|
+
* @param promise - The promise to track
|
|
24
|
+
* @param text - The text to display
|
|
25
|
+
* @returns The result of the promise
|
|
26
|
+
*/
|
|
27
|
+
async function withSpinner(promise, text) {
|
|
28
|
+
const spinner = createSpinner(text);
|
|
29
|
+
try {
|
|
30
|
+
const result = await promise;
|
|
31
|
+
spinner.succeed(`[DONE] ${text}`);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
spinner.fail(`[FAILED] ${text}`);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.storage = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const CONFIG_DIR = process.env.YAMO_CONFIG_DIR || path_1.default.join(os_1.default.homedir(), '.yamo');
|
|
11
|
+
const CONFIG_FILE = path_1.default.join(CONFIG_DIR, 'config.json');
|
|
12
|
+
/**
|
|
13
|
+
* Handles persistent storage of local YAMO configuration.
|
|
14
|
+
*/
|
|
15
|
+
exports.storage = {
|
|
16
|
+
/**
|
|
17
|
+
* Ensures the config directory exists.
|
|
18
|
+
*/
|
|
19
|
+
ensureDir() {
|
|
20
|
+
if (!fs_1.default.existsSync(CONFIG_DIR)) {
|
|
21
|
+
fs_1.default.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Reads the configuration file.
|
|
26
|
+
*/
|
|
27
|
+
read() {
|
|
28
|
+
if (!fs_1.default.existsSync(CONFIG_FILE)) {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const data = fs_1.default.readFileSync(CONFIG_FILE, 'utf8');
|
|
33
|
+
return JSON.parse(data);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Writes the configuration file.
|
|
41
|
+
*/
|
|
42
|
+
write(config) {
|
|
43
|
+
this.ensureDir();
|
|
44
|
+
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Sets a value in the configuration.
|
|
48
|
+
*/
|
|
49
|
+
set(key, value) {
|
|
50
|
+
const configData = this.read();
|
|
51
|
+
configData[key] = value;
|
|
52
|
+
this.write(configData);
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Gets a value from the configuration.
|
|
56
|
+
*/
|
|
57
|
+
get(key) {
|
|
58
|
+
const configData = this.read();
|
|
59
|
+
return configData[key];
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Removes a key from the configuration.
|
|
63
|
+
*/
|
|
64
|
+
remove(key) {
|
|
65
|
+
const configData = this.read();
|
|
66
|
+
const remaining = Object.fromEntries(Object.entries(configData).filter(([k]) => k !== key));
|
|
67
|
+
this.write(remaining);
|
|
68
|
+
},
|
|
69
|
+
};
|