hybrid 1.0.9 → 1.1.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/cli.cjs +644 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/{src/cli.d.ts → cli.d.ts} +0 -1
- package/dist/cli.js +623 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +644 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +623 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -57
- package/src/cli.ts +544 -121
- package/dist/src/cli.js +0 -276
- package/dist/src/core/agent.d.ts +0 -187
- package/dist/src/core/agent.js +0 -225
- package/dist/src/core/plugin.d.ts +0 -114
- package/dist/src/core/plugin.js +0 -123
- package/dist/src/core/tool.d.ts +0 -62
- package/dist/src/core/tool.js +0 -58
- package/dist/src/index.d.ts +0 -13
- package/dist/src/index.js +0 -7
- package/dist/src/lib/jwt.d.ts +0 -88
- package/dist/src/lib/jwt.js +0 -134
- package/dist/src/lib/render.d.ts +0 -3
- package/dist/src/lib/render.js +0 -7
- package/dist/src/ponder/endpoints.d.ts +0 -3
- package/dist/src/ponder/endpoints.js +0 -57
- package/dist/src/ponder/forwarder.d.ts +0 -22
- package/dist/src/ponder/forwarder.js +0 -111
- package/dist/src/ponder/index.d.ts +0 -2
- package/dist/src/ponder/index.js +0 -2
- package/dist/src/ponder/plugin.d.ts +0 -11
- package/dist/src/ponder/plugin.js +0 -19
- package/dist/src/server/listen.d.ts +0 -130
- package/dist/src/server/listen.js +0 -163
- package/dist/src/server/processor.d.ts +0 -24
- package/dist/src/server/processor.js +0 -203
- package/dist/src/types.d.ts +0 -28
- package/dist/src/types.js +0 -1
- package/dist/src/xmtp/endpoints.d.ts +0 -6
- package/dist/src/xmtp/endpoints.js +0 -230
- package/dist/src/xmtp/plugin.d.ts +0 -23
- package/dist/src/xmtp/plugin.js +0 -32
- package/dist/templates/README.md +0 -164
- package/dist/templates/agent.ts +0 -53
- package/dist/templates/env.template +0 -15
- package/dist/templates/gitignore.template +0 -45
- package/dist/templates/package.json +0 -40
- package/dist/templates/src/agent.test.ts +0 -11
- package/dist/templates/tsconfig.json +0 -22
- package/dist/templates/vitest.config.ts +0 -14
- package/src/core/agent.ts +0 -456
- package/src/core/plugin.ts +0 -178
- package/src/core/tool.ts +0 -137
- package/src/index.ts +0 -16
- package/src/lib/jwt.ts +0 -174
- package/src/lib/render.ts +0 -9
- package/src/ponder/endpoints.ts +0 -71
- package/src/ponder/forwarder.ts +0 -149
- package/src/ponder/index.ts +0 -2
- package/src/ponder/plugin.ts +0 -22
- package/src/server/listen.ts +0 -242
- package/src/server/processor.ts +0 -293
- package/src/types.ts +0 -38
- package/src/xmtp/endpoints.ts +0 -314
- package/src/xmtp/plugin.ts +0 -50
- package/templates/README.md +0 -164
- package/templates/agent.ts +0 -53
- package/templates/env.template +0 -15
- package/templates/gitignore.template +0 -45
- package/templates/package.json +0 -40
- package/templates/src/agent.test.ts +0 -11
- package/templates/tsconfig.json +0 -22
- package/templates/vitest.config.ts +0 -14
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// ../../node_modules/.pnpm/tsup@8.5.0_postcss@8.5.6_tsx@4.19.3_typescript@5.9.2/node_modules/tsup/assets/cjs_shims.js
|
|
27
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
|
|
28
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
29
|
+
|
|
30
|
+
// src/cli.ts
|
|
31
|
+
var import_xmtp = require("@hybrd/xmtp");
|
|
32
|
+
var import_degit = __toESM(require("degit"), 1);
|
|
33
|
+
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
34
|
+
var import_node_child_process = require("child_process");
|
|
35
|
+
var import_node_crypto = require("crypto");
|
|
36
|
+
var import_node_fs = require("fs");
|
|
37
|
+
var import_promises = require("fs/promises");
|
|
38
|
+
var import_node_path = require("path");
|
|
39
|
+
var import_node_readline = require("readline");
|
|
40
|
+
var import_node_url = require("url");
|
|
41
|
+
var import_uint8arrays = require("uint8arrays");
|
|
42
|
+
var import_accounts = require("viem/accounts");
|
|
43
|
+
var __dirname = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
44
|
+
var nodeVersion = process.versions.node;
|
|
45
|
+
var [major] = nodeVersion.split(".").map(Number);
|
|
46
|
+
if (!major || major < 20) {
|
|
47
|
+
console.error("Error: Node.js version 20 or higher is required");
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
function generateEncryptionKeyHex() {
|
|
51
|
+
const uint8Array = (0, import_node_crypto.getRandomValues)(new Uint8Array(32));
|
|
52
|
+
return (0, import_uint8arrays.toString)(uint8Array, "hex");
|
|
53
|
+
}
|
|
54
|
+
async function generateKeys(writeToFile = false) {
|
|
55
|
+
console.log("\u{1F511} Generating XMTP keys...");
|
|
56
|
+
const walletKey = (0, import_accounts.generatePrivateKey)();
|
|
57
|
+
const account = (0, import_accounts.privateKeyToAccount)(walletKey);
|
|
58
|
+
const encryptionKeyHex = generateEncryptionKeyHex();
|
|
59
|
+
const publicKey = account.address;
|
|
60
|
+
console.log("\n\u2705 Keys generated successfully!");
|
|
61
|
+
if (writeToFile) {
|
|
62
|
+
try {
|
|
63
|
+
const envContent = `# XMTP Configuration
|
|
64
|
+
XMTP_WALLET_KEY=${walletKey}
|
|
65
|
+
XMTP_ENCRYPTION_KEY=${encryptionKeyHex}
|
|
66
|
+
XMTP_ENV=dev
|
|
67
|
+
|
|
68
|
+
# OpenRouter Configuration
|
|
69
|
+
# Get your OpenRouter API key from https://openrouter.ai/keys
|
|
70
|
+
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
71
|
+
|
|
72
|
+
# Server Configuration (optional)
|
|
73
|
+
# PORT=8454
|
|
74
|
+
`;
|
|
75
|
+
await (0, import_promises.writeFile)(".env", envContent);
|
|
76
|
+
console.log("\n\u{1F4C1} Environment variables written to .env file");
|
|
77
|
+
console.log(`\u{1F50D} Your public key (wallet address): ${publicKey}`);
|
|
78
|
+
console.log("\n\u{1F4DD} Next steps:");
|
|
79
|
+
console.log("1. Add your OPENROUTER_API_KEY to the .env file");
|
|
80
|
+
console.log(
|
|
81
|
+
"2. Set XMTP_ENV to 'dev' for development or 'production' for mainnet"
|
|
82
|
+
);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error("\u274C Failed to write .env file:", error);
|
|
85
|
+
console.log("\n\u{1F4CB} Use these environment variables instead:");
|
|
86
|
+
console.log("=".repeat(60));
|
|
87
|
+
console.log(`XMTP_WALLET_KEY=${walletKey}`);
|
|
88
|
+
console.log(`XMTP_ENCRYPTION_KEY=${encryptionKeyHex}`);
|
|
89
|
+
console.log(`XMTP_ENV=dev`);
|
|
90
|
+
console.log("=".repeat(60));
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
console.log(`XMTP_WALLET_KEY=${walletKey}`);
|
|
94
|
+
console.log(`XMTP_ENCRYPTION_KEY=${encryptionKeyHex}`);
|
|
95
|
+
console.log(`XMTP_ENV=dev`);
|
|
96
|
+
console.log(`
|
|
97
|
+
# Your public key (wallet address): ${publicKey}`);
|
|
98
|
+
}
|
|
99
|
+
console.log(
|
|
100
|
+
"\n\u26A0\uFE0F Keep these keys secure and never commit them to version control!"
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
async function registerWallet() {
|
|
104
|
+
console.log("\u{1F680} Starting XMTP Production Network Registration...");
|
|
105
|
+
const { XMTP_WALLET_KEY } = (0, import_xmtp.validateEnvironment)([
|
|
106
|
+
"XMTP_WALLET_KEY",
|
|
107
|
+
"XMTP_ENCRYPTION_KEY"
|
|
108
|
+
]);
|
|
109
|
+
if (!XMTP_WALLET_KEY) {
|
|
110
|
+
console.error("\u274C XMTP_WALLET_KEY is required for registration");
|
|
111
|
+
console.log("\u{1F4A1} Run 'hybrid gen:keys --write' to generate keys first");
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
console.log("\u{1F511} Creating signer...");
|
|
116
|
+
const signer = (0, import_xmtp.createSigner)(XMTP_WALLET_KEY);
|
|
117
|
+
const identifier = await signer.getIdentifier();
|
|
118
|
+
const address = identifier.identifier;
|
|
119
|
+
console.log(`\u{1F4CD} Wallet Address: ${address}`);
|
|
120
|
+
console.log("\u{1F310} Connecting to XMTP Production Network...");
|
|
121
|
+
console.log("\u26A0\uFE0F This will prompt you to sign messages in your wallet");
|
|
122
|
+
console.log(" - 'XMTP : Authenticate to inbox' message");
|
|
123
|
+
console.log(" - 'Grant messaging access to app' message");
|
|
124
|
+
console.log(" - 'Create inbox' message (if first time)");
|
|
125
|
+
const client = await (0, import_xmtp.createXMTPClient)(XMTP_WALLET_KEY);
|
|
126
|
+
console.log("\u2705 Successfully connected to XMTP Production Network!");
|
|
127
|
+
await (0, import_xmtp.logAgentDetails)(client);
|
|
128
|
+
console.log("\u{1F4E1} Syncing conversations...");
|
|
129
|
+
await client.conversations.sync();
|
|
130
|
+
const conversations = await client.conversations.list();
|
|
131
|
+
console.log(`\u{1F4AC} Found ${conversations.length} existing conversations`);
|
|
132
|
+
console.log("\u{1F389} Registration Complete!");
|
|
133
|
+
console.log(`
|
|
134
|
+
\u2713 Wallet ${address} is now registered on XMTP Production Network
|
|
135
|
+
\u2713 Inbox ID: ${client.inboxId}
|
|
136
|
+
\u2713 Ready to receive messages on production network
|
|
137
|
+
|
|
138
|
+
Next steps:
|
|
139
|
+
1. Update your environment: XMTP_ENV=production
|
|
140
|
+
2. Start your listener service
|
|
141
|
+
3. Share your address for others to message: ${address}
|
|
142
|
+
4. Test messaging at: https://xmtp.chat/dm/${address}
|
|
143
|
+
`);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error("\u274C Registration failed:", error);
|
|
146
|
+
if (error instanceof Error) {
|
|
147
|
+
if (error.message.includes("User rejected")) {
|
|
148
|
+
console.log(
|
|
149
|
+
"\u{1F4DD} Registration was cancelled. You need to approve the wallet signatures to complete registration."
|
|
150
|
+
);
|
|
151
|
+
} else if (error.message.includes("network")) {
|
|
152
|
+
console.log(
|
|
153
|
+
"\u{1F310} Network connection issue. Please check your internet connection and try again."
|
|
154
|
+
);
|
|
155
|
+
} else {
|
|
156
|
+
console.log("\u{1F4A1} Make sure your wallet is connected and try again.");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async function revokeInstallations(inboxId) {
|
|
163
|
+
console.log(`\u{1F527} Revoking XMTP installations for inbox: ${inboxId}`);
|
|
164
|
+
const { XMTP_WALLET_KEY } = process.env;
|
|
165
|
+
if (!XMTP_WALLET_KEY) {
|
|
166
|
+
console.error("\u274C XMTP_WALLET_KEY is required");
|
|
167
|
+
console.log("\u{1F4A1} Run 'hybrid gen:keys --write' to generate keys first");
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const signer = (0, import_xmtp.createSigner)(XMTP_WALLET_KEY);
|
|
172
|
+
const identifier = await signer.getIdentifier();
|
|
173
|
+
const address = identifier.identifier;
|
|
174
|
+
console.log(`\u{1F511} Wallet Address: ${address}`);
|
|
175
|
+
console.log(`\u{1F4CB} Inbox ID: ${inboxId}`);
|
|
176
|
+
console.log("\u{1F50D} Getting inbox state...");
|
|
177
|
+
const inboxStates = await import_xmtp.Client.inboxStateFromInboxIds(
|
|
178
|
+
[inboxId],
|
|
179
|
+
process.env.XMTP_ENV || "dev"
|
|
180
|
+
);
|
|
181
|
+
if (!inboxStates[0]) {
|
|
182
|
+
console.log("\u274C No inbox state found for the provided inboxId");
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
const toRevokeInstallationBytes = inboxStates[0].installations.map(
|
|
186
|
+
(i) => i.bytes
|
|
187
|
+
);
|
|
188
|
+
if (toRevokeInstallationBytes.length === 0) {
|
|
189
|
+
console.log("\u2139\uFE0F No installations found to revoke");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
console.log(
|
|
193
|
+
`\u{1F527} Revoking ${toRevokeInstallationBytes.length} installations...`
|
|
194
|
+
);
|
|
195
|
+
await import_xmtp.Client.revokeInstallations(
|
|
196
|
+
signer,
|
|
197
|
+
inboxId,
|
|
198
|
+
toRevokeInstallationBytes,
|
|
199
|
+
process.env.XMTP_ENV || "dev"
|
|
200
|
+
);
|
|
201
|
+
const resultingStates = await import_xmtp.Client.inboxStateFromInboxIds(
|
|
202
|
+
[inboxId],
|
|
203
|
+
process.env.XMTP_ENV || "dev"
|
|
204
|
+
);
|
|
205
|
+
console.log(
|
|
206
|
+
`\u2705 Successfully revoked installations: ${toRevokeInstallationBytes.length} installations`
|
|
207
|
+
);
|
|
208
|
+
console.log(
|
|
209
|
+
`\u{1F4CB} Resulting state: ${resultingStates[0]?.installations.length || 0} installations remaining`
|
|
210
|
+
);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error("\u274C Error during installation revocation:", error);
|
|
213
|
+
if (error instanceof Error) {
|
|
214
|
+
if (error.message.includes("Missing existing member")) {
|
|
215
|
+
console.log(
|
|
216
|
+
"\n\u{1F4A1} This inbox ID may not exist or may be on a different environment"
|
|
217
|
+
);
|
|
218
|
+
console.log(
|
|
219
|
+
" 1. Check if you're using the correct XMTP_ENV (dev vs production)"
|
|
220
|
+
);
|
|
221
|
+
console.log(" 2. Verify the inbox ID is correct");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function revokeAllInstallations() {
|
|
228
|
+
console.log("\u{1F504} Revoking ALL XMTP Installations");
|
|
229
|
+
console.log("==================================");
|
|
230
|
+
const { XMTP_WALLET_KEY } = process.env;
|
|
231
|
+
if (!XMTP_WALLET_KEY) {
|
|
232
|
+
console.error("\u274C XMTP_WALLET_KEY is required");
|
|
233
|
+
console.log("\u{1F4A1} Run 'hybrid gen:keys --write' to generate keys first");
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
console.log(`\u{1F310} Environment: ${process.env.XMTP_ENV || "dev"}`);
|
|
238
|
+
try {
|
|
239
|
+
const client = await (0, import_xmtp.createXMTPClient)(XMTP_WALLET_KEY);
|
|
240
|
+
const currentInboxId = client.inboxId;
|
|
241
|
+
console.log(`\u{1F4E7} Current Inbox ID: ${currentInboxId}`);
|
|
242
|
+
console.log("\u{1F527} Attempting to revoke all installations for this inbox...");
|
|
243
|
+
await revokeInstallations(currentInboxId);
|
|
244
|
+
console.log("\u2705 Successfully revoked all installations");
|
|
245
|
+
} catch (clientError) {
|
|
246
|
+
console.log(
|
|
247
|
+
"\u26A0\uFE0F Could not create client, attempting alternative approach..."
|
|
248
|
+
);
|
|
249
|
+
console.log("\u{1F50D} This might indicate installation limit issues");
|
|
250
|
+
console.log("\u{1F4A1} You may need to:");
|
|
251
|
+
console.log(" 1. Wait a few minutes and try again");
|
|
252
|
+
console.log(" 2. Use the specific inbox ID if you know it");
|
|
253
|
+
console.log(" 3. Try switching XMTP environments (dev <-> production)");
|
|
254
|
+
throw clientError;
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error("\u{1F4A5} Error revoking installations:", error);
|
|
258
|
+
if (error instanceof Error) {
|
|
259
|
+
if (error.message.includes("5/5 installations")) {
|
|
260
|
+
console.log("\n\u{1F4A1} Installation limit reached. Possible solutions:");
|
|
261
|
+
console.log(" 1. Wait 24 hours for installations to expire");
|
|
262
|
+
console.log(
|
|
263
|
+
" 2. Try switching XMTP environments (dev <-> production)"
|
|
264
|
+
);
|
|
265
|
+
console.log(" 3. Use a different wallet");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function prompt(question) {
|
|
272
|
+
const rl = (0, import_node_readline.createInterface)({
|
|
273
|
+
input: process.stdin,
|
|
274
|
+
output: process.stdout
|
|
275
|
+
});
|
|
276
|
+
return new Promise((resolve) => {
|
|
277
|
+
rl.question(question, (answer) => {
|
|
278
|
+
rl.close();
|
|
279
|
+
resolve(answer);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function replaceTemplateVariables(content, variables) {
|
|
284
|
+
return content.replace(
|
|
285
|
+
/\{\{(\w+)\}\}/g,
|
|
286
|
+
(match, key) => variables[key] || match
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
async function initializeProject() {
|
|
290
|
+
console.log("\u{1F680} Creating a new Hybrid project...");
|
|
291
|
+
const projectNameArg = process.argv[3];
|
|
292
|
+
let projectName = projectNameArg;
|
|
293
|
+
if (projectNameArg === "") {
|
|
294
|
+
console.error("\u274C Project name is required");
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
if (!projectName || !projectName.trim()) {
|
|
298
|
+
while (!projectName || !projectName.trim()) {
|
|
299
|
+
projectName = await prompt("Enter project name: ");
|
|
300
|
+
if (!projectName || !projectName.trim()) {
|
|
301
|
+
console.log("\u274C Project name is required. Please enter a valid name.");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const sanitizedName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
306
|
+
const currentDir = process.cwd();
|
|
307
|
+
const projectDir = projectName === "." ? currentDir : (0, import_node_path.join)(currentDir, sanitizedName);
|
|
308
|
+
if (projectName !== ".") {
|
|
309
|
+
try {
|
|
310
|
+
const existingFiles = await (0, import_promises.readdir)(projectDir);
|
|
311
|
+
if (existingFiles.length > 0) {
|
|
312
|
+
console.error(
|
|
313
|
+
`\u274C Directory "${sanitizedName}" already exists and is not empty`
|
|
314
|
+
);
|
|
315
|
+
console.error(
|
|
316
|
+
"Please choose a different name or remove the existing directory"
|
|
317
|
+
);
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
} catch {
|
|
321
|
+
}
|
|
322
|
+
} else {
|
|
323
|
+
try {
|
|
324
|
+
const existingFiles = await (0, import_promises.readdir)(currentDir);
|
|
325
|
+
const significantFiles = existingFiles.filter(
|
|
326
|
+
(file) => !file.startsWith(".") && file !== "node_modules" && file !== "package-lock.json" && file !== "yarn.lock" && file !== "pnpm-lock.yaml"
|
|
327
|
+
);
|
|
328
|
+
if (significantFiles.length > 0) {
|
|
329
|
+
console.error(
|
|
330
|
+
`\u274C Current directory already exists and is not empty`
|
|
331
|
+
);
|
|
332
|
+
console.error(
|
|
333
|
+
"Please choose a different directory or remove existing files"
|
|
334
|
+
);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
} catch {
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
console.log("\u{1F4E6} Downloading template from GitHub...");
|
|
341
|
+
let templateDownloaded = false;
|
|
342
|
+
try {
|
|
343
|
+
const repoEnv = process.env.REPO || "ian/hybrid#chore/degit-templates";
|
|
344
|
+
let templateRepo;
|
|
345
|
+
if (repoEnv.includes("#")) {
|
|
346
|
+
const [repo, branch] = repoEnv.split("#");
|
|
347
|
+
templateRepo = `${repo}/templates/agent#${branch}`;
|
|
348
|
+
console.log(`\u{1F517} Using repository: ${repo} (branch: ${branch})`);
|
|
349
|
+
} else {
|
|
350
|
+
templateRepo = `${repoEnv}/templates/agent`;
|
|
351
|
+
console.log(`\u{1F517} Using repository: ${repoEnv} (default branch)`);
|
|
352
|
+
}
|
|
353
|
+
const emitter = (0, import_degit.default)(templateRepo, {
|
|
354
|
+
cache: false,
|
|
355
|
+
force: true,
|
|
356
|
+
verbose: false
|
|
357
|
+
});
|
|
358
|
+
await emitter.clone(projectDir);
|
|
359
|
+
console.log(`\u2705 Template downloaded from GitHub to: ${sanitizedName}`);
|
|
360
|
+
templateDownloaded = true;
|
|
361
|
+
} catch (error) {
|
|
362
|
+
console.error(
|
|
363
|
+
"\u274C Failed to download template from GitHub:",
|
|
364
|
+
error instanceof Error ? error.message : String(error)
|
|
365
|
+
);
|
|
366
|
+
console.log(
|
|
367
|
+
"\u{1F4A1} Make sure you have internet connection and the repository/branch exists"
|
|
368
|
+
);
|
|
369
|
+
process.exit(1);
|
|
370
|
+
}
|
|
371
|
+
if (!templateDownloaded) {
|
|
372
|
+
console.error("\u274C Could not download or copy template");
|
|
373
|
+
process.exit(1);
|
|
374
|
+
}
|
|
375
|
+
const variables = {
|
|
376
|
+
projectName: sanitizedName
|
|
377
|
+
};
|
|
378
|
+
try {
|
|
379
|
+
const filesToUpdate = [
|
|
380
|
+
(0, import_node_path.join)(projectDir, "package.json"),
|
|
381
|
+
(0, import_node_path.join)(projectDir, "README.md")
|
|
382
|
+
];
|
|
383
|
+
for (const filePath of filesToUpdate) {
|
|
384
|
+
try {
|
|
385
|
+
let content = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
386
|
+
content = replaceTemplateVariables(content, variables);
|
|
387
|
+
await (0, import_promises.writeFile)(filePath, content, "utf-8");
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.log(
|
|
390
|
+
`\u26A0\uFE0F Could not update ${filePath.split("/").pop()}: file not found`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
console.log("\u2705 Template variables updated");
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error("\u274C Failed to update template variables:", error);
|
|
397
|
+
}
|
|
398
|
+
console.log("\n\u{1F389} Hybrid project created successfully!");
|
|
399
|
+
console.log(`
|
|
400
|
+
\u{1F4C2} Project created in: ${projectDir}`);
|
|
401
|
+
console.log("\n\u{1F4CB} Next steps:");
|
|
402
|
+
console.log(`1. cd ${sanitizedName}`);
|
|
403
|
+
console.log(
|
|
404
|
+
"2. Install dependencies (npm install, yarn install, or pnpm install)"
|
|
405
|
+
);
|
|
406
|
+
console.log("3. Get your OpenRouter API key from https://openrouter.ai/keys");
|
|
407
|
+
console.log("4. Add your API key to the OPENROUTER_API_KEY in .env");
|
|
408
|
+
console.log("5. Set XMTP_ENV in .env (dev or production)");
|
|
409
|
+
console.log("6. Generate keys: npm run keys (or yarn/pnpm equivalent)");
|
|
410
|
+
console.log("7. Start development: npm run dev (or yarn/pnpm equivalent)");
|
|
411
|
+
console.log(
|
|
412
|
+
"\n\u{1F4D6} For more information, see the README.md file in your project"
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
function runDev() {
|
|
416
|
+
console.log("Starting development server...");
|
|
417
|
+
const envPath = (0, import_node_path.join)(process.cwd(), ".env");
|
|
418
|
+
if ((0, import_node_fs.existsSync)(envPath)) {
|
|
419
|
+
import_dotenv.default.config({ path: envPath });
|
|
420
|
+
console.log("\u2705 Loaded environment variables from .env");
|
|
421
|
+
} else {
|
|
422
|
+
console.log("\u26A0\uFE0F No .env file found - environment variables not loaded");
|
|
423
|
+
}
|
|
424
|
+
const child = (0, import_node_child_process.spawn)("tsx", ["--watch", "src/agent.ts"], {
|
|
425
|
+
stdio: "inherit",
|
|
426
|
+
shell: true
|
|
427
|
+
});
|
|
428
|
+
child.on("error", (error) => {
|
|
429
|
+
console.error("Failed to start dev server:", error);
|
|
430
|
+
process.exit(1);
|
|
431
|
+
});
|
|
432
|
+
child.on("exit", (code) => {
|
|
433
|
+
process.exit(code ?? 0);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
function runBuild() {
|
|
437
|
+
console.log("Building project...");
|
|
438
|
+
const child = (0, import_node_child_process.spawn)("tsc", [], {
|
|
439
|
+
stdio: "inherit",
|
|
440
|
+
shell: true
|
|
441
|
+
});
|
|
442
|
+
child.on("error", (error) => {
|
|
443
|
+
console.error("Failed to build project:", error);
|
|
444
|
+
process.exit(1);
|
|
445
|
+
});
|
|
446
|
+
child.on("exit", (code) => {
|
|
447
|
+
if (code === 0) {
|
|
448
|
+
console.log("Build completed successfully");
|
|
449
|
+
} else {
|
|
450
|
+
console.error("Build failed");
|
|
451
|
+
process.exit(code ?? 1);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
async function runRegister() {
|
|
456
|
+
const envPath = (0, import_node_path.join)(process.cwd(), ".env");
|
|
457
|
+
if ((0, import_node_fs.existsSync)(envPath)) {
|
|
458
|
+
import_dotenv.default.config({ path: envPath });
|
|
459
|
+
console.log("\u2705 Loaded environment variables from .env");
|
|
460
|
+
} else {
|
|
461
|
+
console.log("\u26A0\uFE0F No .env file found - environment variables not loaded");
|
|
462
|
+
}
|
|
463
|
+
try {
|
|
464
|
+
await registerWallet();
|
|
465
|
+
} catch (error) {
|
|
466
|
+
console.error("Failed to run registration:", error);
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async function runRevoke() {
|
|
471
|
+
const inboxId = process.argv[3];
|
|
472
|
+
if (!inboxId) {
|
|
473
|
+
console.error("\u274C InboxID is required");
|
|
474
|
+
console.error("Usage: hybrid revoke <inboxId>");
|
|
475
|
+
process.exit(1);
|
|
476
|
+
}
|
|
477
|
+
const envPath = (0, import_node_path.join)(process.cwd(), ".env");
|
|
478
|
+
if ((0, import_node_fs.existsSync)(envPath)) {
|
|
479
|
+
import_dotenv.default.config({ path: envPath });
|
|
480
|
+
console.log("\u2705 Loaded environment variables from .env");
|
|
481
|
+
} else {
|
|
482
|
+
console.log("\u26A0\uFE0F No .env file found - environment variables not loaded");
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
await revokeInstallations(inboxId);
|
|
486
|
+
} catch (error) {
|
|
487
|
+
console.error("Failed to run revocation:", error);
|
|
488
|
+
process.exit(1);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
async function runRevokeAll() {
|
|
492
|
+
const envPath = (0, import_node_path.join)(process.cwd(), ".env");
|
|
493
|
+
if ((0, import_node_fs.existsSync)(envPath)) {
|
|
494
|
+
import_dotenv.default.config({ path: envPath });
|
|
495
|
+
console.log("\u2705 Loaded environment variables from .env");
|
|
496
|
+
} else {
|
|
497
|
+
console.log("\u26A0\uFE0F No .env file found - environment variables not loaded");
|
|
498
|
+
}
|
|
499
|
+
try {
|
|
500
|
+
await revokeAllInstallations();
|
|
501
|
+
} catch (error) {
|
|
502
|
+
console.error("Failed to run revoke all:", error);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
async function main() {
|
|
507
|
+
const command = process.argv[2];
|
|
508
|
+
switch (command) {
|
|
509
|
+
case "init":
|
|
510
|
+
try {
|
|
511
|
+
await initializeProject();
|
|
512
|
+
} catch (error) {
|
|
513
|
+
console.error("Failed to initialize project:", error);
|
|
514
|
+
console.error("Error details:", error instanceof Error ? error.stack : String(error));
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
case "dev":
|
|
519
|
+
runDev();
|
|
520
|
+
break;
|
|
521
|
+
case "gen:keys":
|
|
522
|
+
try {
|
|
523
|
+
const writeFlag = process.argv.includes("--write");
|
|
524
|
+
await generateKeys(writeFlag);
|
|
525
|
+
} catch (error) {
|
|
526
|
+
console.error("Failed to generate keys:", error);
|
|
527
|
+
process.exit(1);
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
case "register":
|
|
531
|
+
try {
|
|
532
|
+
await runRegister();
|
|
533
|
+
} catch (error) {
|
|
534
|
+
console.error("Failed to register:", error);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
}
|
|
537
|
+
break;
|
|
538
|
+
case "revoke":
|
|
539
|
+
try {
|
|
540
|
+
await runRevoke();
|
|
541
|
+
} catch (error) {
|
|
542
|
+
console.error("Failed to revoke:", error);
|
|
543
|
+
process.exit(1);
|
|
544
|
+
}
|
|
545
|
+
break;
|
|
546
|
+
case "revoke:all":
|
|
547
|
+
try {
|
|
548
|
+
await runRevokeAll();
|
|
549
|
+
} catch (error) {
|
|
550
|
+
console.error("Failed to revoke all:", error);
|
|
551
|
+
process.exit(1);
|
|
552
|
+
}
|
|
553
|
+
break;
|
|
554
|
+
case "build":
|
|
555
|
+
runBuild();
|
|
556
|
+
break;
|
|
557
|
+
case "--help":
|
|
558
|
+
case "-h":
|
|
559
|
+
case "help":
|
|
560
|
+
console.log("Usage: hybrid <command> or hy <command>");
|
|
561
|
+
console.log("");
|
|
562
|
+
console.log("Commands:");
|
|
563
|
+
console.log(" init [name] Create a new Hybrid project");
|
|
564
|
+
console.log(" dev Start development server with watch mode");
|
|
565
|
+
console.log(" build Build the TypeScript project");
|
|
566
|
+
console.log(" gen:keys Generate XMTP wallet and encryption keys");
|
|
567
|
+
console.log(
|
|
568
|
+
" Use --write to save keys directly to .env file"
|
|
569
|
+
);
|
|
570
|
+
console.log(" register Register wallet with XMTP production network");
|
|
571
|
+
console.log(" revoke Revoke XMTP installations for specific inbox");
|
|
572
|
+
console.log(" Usage: hybrid revoke <inboxId>");
|
|
573
|
+
console.log(
|
|
574
|
+
" revoke:all Revoke ALL XMTP installations for current wallet"
|
|
575
|
+
);
|
|
576
|
+
console.log("");
|
|
577
|
+
console.log("Environment Variables:");
|
|
578
|
+
console.log(
|
|
579
|
+
" REPO Set template repository (default: ian/hybrid#chore/degit-templates)"
|
|
580
|
+
);
|
|
581
|
+
console.log(" Format: user/repo or user/repo#branch");
|
|
582
|
+
console.log("");
|
|
583
|
+
console.log("Examples:");
|
|
584
|
+
console.log(" hybrid init my-agent or hy init my-agent");
|
|
585
|
+
console.log(
|
|
586
|
+
" hybrid init or hy init (will prompt for name)"
|
|
587
|
+
);
|
|
588
|
+
console.log(" hybrid dev or hy dev");
|
|
589
|
+
console.log(" hybrid build or hy build");
|
|
590
|
+
console.log(" hybrid gen:keys or hy gen:keys");
|
|
591
|
+
console.log(" hybrid gen:keys --write or hy gen:keys --write");
|
|
592
|
+
console.log(" hybrid register or hy register");
|
|
593
|
+
console.log(" hybrid revoke <inboxId> or hy revoke <inboxId>");
|
|
594
|
+
console.log(" hybrid revoke:all or hy revoke:all");
|
|
595
|
+
console.log("");
|
|
596
|
+
break;
|
|
597
|
+
default:
|
|
598
|
+
console.log("Usage: hybrid <command> or hy <command>");
|
|
599
|
+
console.log("");
|
|
600
|
+
console.log("Commands:");
|
|
601
|
+
console.log(" init [name] Create a new Hybrid project");
|
|
602
|
+
console.log(" dev Start development server with watch mode");
|
|
603
|
+
console.log(" build Build the TypeScript project");
|
|
604
|
+
console.log(" gen:keys Generate XMTP wallet and encryption keys");
|
|
605
|
+
console.log(
|
|
606
|
+
" Use --write to save keys directly to .env file"
|
|
607
|
+
);
|
|
608
|
+
console.log(" register Register wallet with XMTP production network");
|
|
609
|
+
console.log(" revoke Revoke XMTP installations for specific inbox");
|
|
610
|
+
console.log(" Usage: hybrid revoke <inboxId>");
|
|
611
|
+
console.log(
|
|
612
|
+
" revoke:all Revoke ALL XMTP installations for current wallet"
|
|
613
|
+
);
|
|
614
|
+
console.log("");
|
|
615
|
+
console.log("Environment Variables:");
|
|
616
|
+
console.log(
|
|
617
|
+
" REPO Set template repository (default: ian/hybrid#chore/degit-templates)"
|
|
618
|
+
);
|
|
619
|
+
console.log(" Format: user/repo or user/repo#branch");
|
|
620
|
+
console.log("");
|
|
621
|
+
console.log("Examples:");
|
|
622
|
+
console.log(" hybrid init my-agent or hy init my-agent");
|
|
623
|
+
console.log(
|
|
624
|
+
" hybrid init or hy init (will prompt for name)"
|
|
625
|
+
);
|
|
626
|
+
console.log(" hybrid dev or hy dev");
|
|
627
|
+
console.log(" hybrid build or hy build");
|
|
628
|
+
console.log(" hybrid gen:keys or hy gen:keys");
|
|
629
|
+
console.log(" hybrid gen:keys --write or hy gen:keys --write");
|
|
630
|
+
console.log(" hybrid register or hy register");
|
|
631
|
+
console.log(" hybrid revoke <inboxId> or hy revoke <inboxId>");
|
|
632
|
+
console.log(" hybrid revoke:all or hy revoke:all");
|
|
633
|
+
console.log("");
|
|
634
|
+
if (command && !["--help", "-h", "help"].includes(command)) {
|
|
635
|
+
process.exit(1);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
main().catch((error) => {
|
|
640
|
+
console.error("CLI error:", error);
|
|
641
|
+
console.error("Error details:", error instanceof Error ? error.stack : String(error));
|
|
642
|
+
process.exit(1);
|
|
643
|
+
});
|
|
644
|
+
//# sourceMappingURL=cli.cjs.map
|