@yamo/cli 1.0.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/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/index.js +178 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 YAMO Protocol
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 💻 YAMO CLI (v1.0.0 - Protocol v0.4)
|
|
2
|
+
|
|
3
|
+
The Command Line Interface for the YAMO Protocol. Now powered by `@yamo/core`.
|
|
4
|
+
|
|
5
|
+
## 📥 Installation
|
|
6
|
+
|
|
7
|
+
From the monorepo root:
|
|
8
|
+
```bash
|
|
9
|
+
npm install
|
|
10
|
+
npm run build --workspaces
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## ⚙️ Configuration (.env)
|
|
14
|
+
Create a `.env` file in `packages/cli`:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
CONTRACT_ADDRESS=0xe7f1...
|
|
18
|
+
RPC_URL=http://127.0.0.1:8545
|
|
19
|
+
PRIVATE_KEY=0x...
|
|
20
|
+
|
|
21
|
+
# IPFS Settings
|
|
22
|
+
USE_REAL_IPFS=true
|
|
23
|
+
PINATA_JWT=eyJ...
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 📖 Commands
|
|
27
|
+
|
|
28
|
+
### `yamo init <agent_name>`
|
|
29
|
+
Creates a new `block.yamo` template.
|
|
30
|
+
|
|
31
|
+
### `yamo hash <file>`
|
|
32
|
+
Calculates the content hash formatted for blockchain submission.
|
|
33
|
+
|
|
34
|
+
### `yamo submit <file>`
|
|
35
|
+
Submits a block to the chain.
|
|
36
|
+
* `--ipfs`: Uploads content to IPFS. If the YAMO file contains `output: file.json;`, it will automatically create a **Deep Bundle** containing both the trace and the artifact.
|
|
37
|
+
* `-e, --encrypt`: Encrypts the IPFS bundle using AES-256-GCM.
|
|
38
|
+
* `-k, --key <string>`: The passphrase for encryption (or use `YAMO_ENCRYPTION_KEY` env var).
|
|
39
|
+
|
|
40
|
+
### `yamo audit <blockId>`
|
|
41
|
+
Performs a cryptographic integrity check.
|
|
42
|
+
1. Fetches block data from the chain.
|
|
43
|
+
2. Downloads content from IPFS.
|
|
44
|
+
3. Re-hashes the content locally.
|
|
45
|
+
4. Asserts `LocalHash === ChainHash`.
|
|
46
|
+
|
|
47
|
+
* `-k, --key <string>`: Passphrase to decrypt the content if the bundle is encrypted.
|
|
48
|
+
|
|
49
|
+
## 🔒 Encryption
|
|
50
|
+
|
|
51
|
+
YAMO v1.0 supports optional client-side encryption for IPFS bundles.
|
|
52
|
+
- **Algorithm**: AES-256-GCM (Authenticated Encryption).
|
|
53
|
+
- **Key Derivation**: Keys are derived from your passphrase using `scrypt` with a random salt.
|
|
54
|
+
- **Metadata**: Encrypted bundles include an `encryption_metadata.json` file with the salt and IVs. The actual content is opaque.
|
|
55
|
+
|
|
56
|
+
**Example Encrypted Workflow:**
|
|
57
|
+
```bash
|
|
58
|
+
# Submit
|
|
59
|
+
yamo submit task.yamo --id 123 --ipfs --encrypt --key "my-secret"
|
|
60
|
+
|
|
61
|
+
# Audit
|
|
62
|
+
yamo audit 123 --key "my-secret"
|
|
63
|
+
```
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
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
|
+
const core_1 = require("@yamo/core");
|
|
47
|
+
dotenv.config();
|
|
48
|
+
const program = new commander_1.Command();
|
|
49
|
+
const ipfsManager = new core_1.IpfsManager();
|
|
50
|
+
const chainClient = new core_1.YamoChainClient();
|
|
51
|
+
program
|
|
52
|
+
.name("yamo")
|
|
53
|
+
.description("YAMO Protocol CLI - Manage Agentic Reasoning Chains")
|
|
54
|
+
.version("0.5.0");
|
|
55
|
+
program
|
|
56
|
+
.command("hash")
|
|
57
|
+
.description("Calculate the content hash of a YAMO block")
|
|
58
|
+
.argument("<file>", "Path to the YAMO file")
|
|
59
|
+
.action((file) => {
|
|
60
|
+
try {
|
|
61
|
+
const content = fs_1.default.readFileSync(file, "utf8").trim();
|
|
62
|
+
const hash = crypto_1.default.createHash("sha256").update(content).digest("hex");
|
|
63
|
+
console.log(chalk_1.default.green("Block Content Hash:"));
|
|
64
|
+
console.log(chalk_1.default.cyan(`0x${hash}`));
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error(chalk_1.default.red(`Error: ${error.message}`));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
program
|
|
71
|
+
.command("init")
|
|
72
|
+
.description("Initialize a new YAMO block template")
|
|
73
|
+
.argument("<agent_name>", "Name of the agent")
|
|
74
|
+
.option("-i, --intent <intent>", "Agent intent", "execute_task")
|
|
75
|
+
.action((agent_name, options) => {
|
|
76
|
+
const template = `
|
|
77
|
+
agent: ${agent_name};
|
|
78
|
+
intent: ${options.intent};
|
|
79
|
+
context:
|
|
80
|
+
platform;yamo_v0.5;
|
|
81
|
+
constraints:
|
|
82
|
+
- human_readable;true;
|
|
83
|
+
priority: medium;
|
|
84
|
+
output: result.json;
|
|
85
|
+
meta: hypothesis;Initial hypothesis;
|
|
86
|
+
meta: confidence;0.9;
|
|
87
|
+
log: session_start;timestamp;${new Date().toISOString()};
|
|
88
|
+
handoff: User;
|
|
89
|
+
`.trim();
|
|
90
|
+
const filename = "block.yamo";
|
|
91
|
+
fs_1.default.writeFileSync(filename, template);
|
|
92
|
+
console.log(chalk_1.default.green(`Created YAMO template: ${chalk_1.default.bold(filename)}`));
|
|
93
|
+
});
|
|
94
|
+
program
|
|
95
|
+
.command("submit")
|
|
96
|
+
.description("Submit a YAMO block to the blockchain")
|
|
97
|
+
.argument("<file>", "Path to the YAMO file")
|
|
98
|
+
.requiredOption("--id <blockId>", "Unique Block ID")
|
|
99
|
+
.option("--prev <previousBlock>", "Previous Block Hash", "0")
|
|
100
|
+
.option("--consensus <type>", "Consensus Type", "cli_manual")
|
|
101
|
+
.option("--ledger <name>", "Ledger Name", "yamo_cli")
|
|
102
|
+
.option("--ipfs", "Upload content to IPFS before submitting")
|
|
103
|
+
.option("-e, --encrypt", "Encrypt the bundle")
|
|
104
|
+
.option("-k, --key <key>", "Encryption key (or set YAMO_ENCRYPTION_KEY)")
|
|
105
|
+
.action(async (file, options) => {
|
|
106
|
+
try {
|
|
107
|
+
const content = fs_1.default.readFileSync(file, "utf8").trim();
|
|
108
|
+
const contentHash = "0x" + crypto_1.default.createHash("sha256").update(content).digest("hex");
|
|
109
|
+
console.log(chalk_1.default.blue(`Calculated Hash: ${contentHash}`));
|
|
110
|
+
let ipfsCID = undefined;
|
|
111
|
+
if (options.ipfs) {
|
|
112
|
+
const outputMatch = content.match(/output:\s*([^;]+);/);
|
|
113
|
+
const files = [{ name: "block.yamo", content }];
|
|
114
|
+
if (outputMatch) {
|
|
115
|
+
const artifactName = outputMatch[1].trim();
|
|
116
|
+
const artifactPath = path_1.default.join(path_1.default.dirname(file), artifactName);
|
|
117
|
+
if (fs_1.default.existsSync(artifactPath)) {
|
|
118
|
+
console.log(chalk_1.default.cyan(`Bundling output: ${artifactName}`));
|
|
119
|
+
files.push({ name: artifactName, content: fs_1.default.readFileSync(artifactPath, "utf8") });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
let encryptionKey = undefined;
|
|
123
|
+
if (options.encrypt) {
|
|
124
|
+
encryptionKey = options.key || process.env.YAMO_ENCRYPTION_KEY;
|
|
125
|
+
if (!encryptionKey) {
|
|
126
|
+
throw new Error("Encryption enabled but no key provided. Use --key or YAMO_ENCRYPTION_KEY.");
|
|
127
|
+
}
|
|
128
|
+
console.log(chalk_1.default.yellow("🔒 Encrypting bundle..."));
|
|
129
|
+
}
|
|
130
|
+
ipfsCID = await ipfsManager.upload({ content, files, encryptionKey });
|
|
131
|
+
console.log(chalk_1.default.cyan(`IPFS Bundle CID: ${ipfsCID}`));
|
|
132
|
+
}
|
|
133
|
+
await chainClient.submitBlock(options.id, options.prev, contentHash, options.consensus, options.ledger, ipfsCID);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.error(chalk_1.default.red(`Error: ${error.message}`));
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
program
|
|
140
|
+
.command("audit")
|
|
141
|
+
.description("Audit a block's integrity (Chain vs IPFS)")
|
|
142
|
+
.argument("<blockId>", "Block ID to audit")
|
|
143
|
+
.option("-k, --key <key>", "Decryption key")
|
|
144
|
+
.action(async (blockId, options) => {
|
|
145
|
+
try {
|
|
146
|
+
console.log(chalk_1.default.blue(`Auditing Block ${blockId}...`));
|
|
147
|
+
const block = await chainClient.getBlock(blockId);
|
|
148
|
+
if (!block) {
|
|
149
|
+
console.error(chalk_1.default.red("Block not found on-chain."));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log(chalk_1.default.gray(`Found on-chain record:`));
|
|
153
|
+
console.log(` Agent: ${block.agentAddress}`);
|
|
154
|
+
console.log(` Hash: ${block.contentHash}`);
|
|
155
|
+
console.log(` IPFS: ${block.ipfsCID || "None"}`);
|
|
156
|
+
if (!block.ipfsCID) {
|
|
157
|
+
console.log(chalk_1.default.yellow("⚠️ No IPFS CID. Cannot perform deep content audit."));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
console.log(chalk_1.default.blue("Fetching content from IPFS..."));
|
|
161
|
+
const key = options.key || process.env.YAMO_ENCRYPTION_KEY;
|
|
162
|
+
const content = await ipfsManager.download(block.ipfsCID, key);
|
|
163
|
+
const calcHash = "0x" + crypto_1.default.createHash("sha256").update(content).digest("hex");
|
|
164
|
+
console.log(` Calculated: ${calcHash}`);
|
|
165
|
+
if (calcHash === block.contentHash) {
|
|
166
|
+
console.log(chalk_1.default.green("✅ INTEGRITY VERIFIED: Content matches chain hash."));
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.log(chalk_1.default.red("❌ INTEGRITY FAILED: Hash mismatch!"));
|
|
170
|
+
console.log(` Expected: ${block.contentHash}`);
|
|
171
|
+
console.log(` Got: ${calcHash}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error(chalk_1.default.red(`Error: ${error.message}`));
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yamo/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "YAMO Protocol v0.4 - Command-line tools for blockchain integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"yamo": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"prepublishOnly": "npm run build",
|
|
18
|
+
"start": "node dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"yamo",
|
|
22
|
+
"cli",
|
|
23
|
+
"blockchain",
|
|
24
|
+
"agent"
|
|
25
|
+
],
|
|
26
|
+
"author": "YAMO Protocol",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/yamo-protocol/yamo-cli.git"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/yamo-protocol/yamo-cli/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/yamo-protocol/yamo-cli#readme",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/form-data": "^2.2.1",
|
|
38
|
+
"@types/node": "^25.0.3",
|
|
39
|
+
"ts-node": "^10.9.2",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@yamo/core": "^1.0.0",
|
|
44
|
+
"axios": "^1.13.2",
|
|
45
|
+
"chalk": "^4.1.2",
|
|
46
|
+
"commander": "^12.0.0",
|
|
47
|
+
"dotenv": "^17.2.3",
|
|
48
|
+
"form-data": "^4.0.5"
|
|
49
|
+
}
|
|
50
|
+
}
|