@clawtrail/init 1.4.2 → 2.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/dist/index.js +156 -316
- package/package.json +1 -3
package/dist/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import inquirer from "inquirer";
|
|
6
5
|
import chalk from "chalk";
|
|
7
6
|
import ora from "ora";
|
|
8
7
|
import fs from "fs/promises";
|
|
@@ -66,107 +65,36 @@ async function downloadSkillFiles(targetDir, staging = false) {
|
|
|
66
65
|
}
|
|
67
66
|
if (failed.length > 0) {
|
|
68
67
|
spinner.warn(
|
|
69
|
-
chalk.yellow(`Downloaded ${succeeded}/${downloads.length}
|
|
68
|
+
chalk.yellow(`Downloaded ${succeeded}/${downloads.length} files (${env}) \u2014 ${failed.join(", ")} unavailable`)
|
|
70
69
|
);
|
|
71
70
|
} else {
|
|
72
71
|
spinner.succeed(
|
|
73
|
-
chalk.green(`Downloaded ${succeeded} skill files
|
|
72
|
+
chalk.green(`Downloaded ${succeeded} skill files (${env})`)
|
|
74
73
|
);
|
|
75
74
|
}
|
|
75
|
+
return { succeeded, failed };
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
function getRegistrationErrorHint(message) {
|
|
84
|
-
const lower = message.toLowerCase();
|
|
85
|
-
for (const [pattern, hint] of Object.entries(REGISTRATION_ERROR_HINTS)) {
|
|
86
|
-
if (lower.includes(pattern)) return hint;
|
|
87
|
-
}
|
|
88
|
-
return void 0;
|
|
89
|
-
}
|
|
90
|
-
async function registerAgent(data, staging = false) {
|
|
91
|
-
const apiUrl = staging ? "https://sapi.clawtrail.ai/ct/api" : "https://api.clawtrail.ai/ct/api";
|
|
92
|
-
const spinner = ora("Registering agent with ClawTrail...").start();
|
|
93
|
-
try {
|
|
94
|
-
const response = await fetch(`${apiUrl}/agents/register`, {
|
|
95
|
-
method: "POST",
|
|
96
|
-
headers: {
|
|
97
|
-
"Content-Type": "application/json"
|
|
98
|
-
},
|
|
99
|
-
body: JSON.stringify(data)
|
|
100
|
-
});
|
|
101
|
-
if (!response.ok) {
|
|
102
|
-
const error = await response.json();
|
|
103
|
-
const rawMessage = error.error || "Registration failed";
|
|
104
|
-
const hint = getRegistrationErrorHint(rawMessage);
|
|
105
|
-
throw new Error(hint || rawMessage);
|
|
106
|
-
}
|
|
107
|
-
const result = await response.json();
|
|
108
|
-
spinner.succeed(chalk.green("Agent registered successfully!"));
|
|
109
|
-
return {
|
|
110
|
-
agentId: result.agentId,
|
|
111
|
-
apiKey: result.apiKey,
|
|
112
|
-
verificationCode: result.verificationCode,
|
|
113
|
-
statusUrl: result.statusUrl
|
|
114
|
-
};
|
|
115
|
-
} catch (error) {
|
|
116
|
-
spinner.fail(chalk.red(`Registration failed: ${error.message}`));
|
|
117
|
-
throw error;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
async function checkExistingApiKey() {
|
|
77
|
+
async function copyToOpenClawDirs(targetDir, staging) {
|
|
78
|
+
const skillFolder = staging ? "clawtrail-staging" : "clawtrail";
|
|
79
|
+
const openclawDir = path.join(os.homedir(), ".openclaw");
|
|
80
|
+
const placed = [];
|
|
81
|
+
const workspaceDir = path.join(openclawDir, "workspace");
|
|
82
|
+
await ensureDirectory(workspaceDir);
|
|
121
83
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return content.includes("CLAWTRAIL_API_KEY=");
|
|
84
|
+
await fs.copyFile(path.join(targetDir, "HEARTBEAT.md"), path.join(workspaceDir, "HEARTBEAT.md"));
|
|
85
|
+
placed.push("~/.openclaw/workspace/HEARTBEAT.md");
|
|
125
86
|
} catch {
|
|
126
|
-
return false;
|
|
127
87
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const envPath = path.join(process.cwd(), ".env");
|
|
131
|
-
const envContent = `
|
|
132
|
-
# ClawTrail API Key
|
|
133
|
-
CLAWTRAIL_API_KEY=${apiKey}
|
|
134
|
-
`;
|
|
135
|
-
try {
|
|
136
|
-
let existingContent = "";
|
|
137
|
-
try {
|
|
138
|
-
existingContent = await fs.readFile(envPath, "utf-8");
|
|
139
|
-
} catch {
|
|
140
|
-
}
|
|
141
|
-
if (existingContent.includes("CLAWTRAIL_API_KEY")) {
|
|
142
|
-
console.log(
|
|
143
|
-
chalk.yellow(
|
|
144
|
-
" .env already contains CLAWTRAIL_API_KEY, not overwriting"
|
|
145
|
-
)
|
|
146
|
-
);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
await fs.appendFile(envPath, envContent);
|
|
150
|
-
console.log(chalk.green(` Saved API key to ${chalk.cyan(".env")}`));
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.log(
|
|
153
|
-
chalk.yellow(` Could not save to .env: ${error.message}`)
|
|
154
|
-
);
|
|
155
|
-
console.log(
|
|
156
|
-
chalk.gray(" You can manually add it: CLAWTRAIL_API_KEY=<your-key>")
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
async function detectOpenClaw() {
|
|
161
|
-
const openClawDir = path.join(os.homedir(), ".openclaw");
|
|
88
|
+
const skillsDir = path.join(openclawDir, "skills", skillFolder);
|
|
89
|
+
await ensureDirectory(skillsDir);
|
|
162
90
|
try {
|
|
163
|
-
await fs.
|
|
164
|
-
|
|
91
|
+
await fs.copyFile(path.join(targetDir, "SKILL.md"), path.join(skillsDir, "SKILL.md"));
|
|
92
|
+
placed.push(`~/.openclaw/skills/${skillFolder}/SKILL.md`);
|
|
165
93
|
} catch {
|
|
166
|
-
return false;
|
|
167
94
|
}
|
|
95
|
+
return placed;
|
|
168
96
|
}
|
|
169
|
-
async function configureOpenClaw(
|
|
97
|
+
async function configureOpenClaw(staging, apiKey) {
|
|
170
98
|
const openClawDir = path.join(os.homedir(), ".openclaw");
|
|
171
99
|
const configPath = path.join(openClawDir, "openclaw.json");
|
|
172
100
|
const apiUrl = staging ? "https://sapi.clawtrail.ai/ct" : "https://api.clawtrail.ai/ct";
|
|
@@ -176,269 +104,181 @@ async function configureOpenClaw(apiKey, staging) {
|
|
|
176
104
|
const existing = await fs.readFile(configPath, "utf-8");
|
|
177
105
|
config = JSON5.parse(existing);
|
|
178
106
|
} catch (err) {
|
|
179
|
-
if (err.code
|
|
180
|
-
} else {
|
|
181
|
-
console.log(
|
|
182
|
-
chalk.yellow(` Could not parse existing openclaw.json \u2014 backing up and starting fresh`)
|
|
183
|
-
);
|
|
107
|
+
if (err.code !== "ENOENT") {
|
|
184
108
|
try {
|
|
185
109
|
await fs.copyFile(configPath, configPath + ".bak");
|
|
186
|
-
console.log(chalk.gray(` Backup saved to ${configPath}.bak`));
|
|
187
110
|
} catch {
|
|
188
111
|
}
|
|
189
112
|
}
|
|
190
113
|
}
|
|
191
|
-
config.
|
|
192
|
-
config.
|
|
193
|
-
config.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
apiKey,
|
|
197
|
-
apiUrl
|
|
198
|
-
}
|
|
114
|
+
config.agents ??= {};
|
|
115
|
+
config.agents.defaults ??= {};
|
|
116
|
+
config.agents.defaults.heartbeat = {
|
|
117
|
+
every: "30s",
|
|
118
|
+
target: "last"
|
|
199
119
|
};
|
|
120
|
+
config.skills ??= {};
|
|
121
|
+
config.skills.entries ??= {};
|
|
122
|
+
config.skills.entries.clawtrail ??= {};
|
|
123
|
+
config.skills.entries.clawtrail.enabled = true;
|
|
124
|
+
config.skills.entries.clawtrail.env ??= {};
|
|
125
|
+
config.skills.entries.clawtrail.env.CLAWTRAIL_API_URL = apiUrl;
|
|
126
|
+
if (apiKey) {
|
|
127
|
+
config.skills.entries.clawtrail.env.CLAWTRAIL_API_KEY = apiKey;
|
|
128
|
+
}
|
|
200
129
|
await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
201
|
-
|
|
130
|
+
return {
|
|
131
|
+
configPath: "~/.openclaw/openclaw.json",
|
|
132
|
+
heartbeat: "every 30s",
|
|
133
|
+
hasApiKey: !!apiKey
|
|
134
|
+
};
|
|
202
135
|
}
|
|
203
|
-
async function
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
const workspaceDir = path.join(openclawDir, "workspace");
|
|
207
|
-
await ensureDirectory(workspaceDir);
|
|
136
|
+
async function registerAgent(name, description, staging, opts = {}) {
|
|
137
|
+
const apiUrl = staging ? "https://sapi.clawtrail.ai/ct/api" : "https://api.clawtrail.ai/ct/api";
|
|
138
|
+
const spinner = ora("Registering agent...").start();
|
|
208
139
|
try {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
140
|
+
const response = await fetch(`${apiUrl}/agents/register`, {
|
|
141
|
+
method: "POST",
|
|
142
|
+
headers: { "Content-Type": "application/json" },
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
name,
|
|
145
|
+
description,
|
|
146
|
+
bio: opts.bio || void 0,
|
|
147
|
+
agentType: opts.agentType || "openclaw",
|
|
148
|
+
framework: opts.framework || void 0,
|
|
149
|
+
skills: opts.skills?.length ? opts.skills : void 0,
|
|
150
|
+
capabilities: opts.capabilities?.length ? opts.capabilities : ["general"]
|
|
151
|
+
})
|
|
152
|
+
});
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const error = await response.json();
|
|
155
|
+
throw new Error(error.error || "Registration failed");
|
|
156
|
+
}
|
|
157
|
+
const result = await response.json();
|
|
158
|
+
spinner.succeed(chalk.green("Agent registered"));
|
|
159
|
+
return {
|
|
160
|
+
agentId: result.agentId,
|
|
161
|
+
apiKey: result.apiKey,
|
|
162
|
+
verificationCode: result.verificationCode,
|
|
163
|
+
statusUrl: result.statusUrl
|
|
164
|
+
};
|
|
165
|
+
} catch (error) {
|
|
166
|
+
spinner.fail(chalk.red(`Registration failed: ${error.message}`));
|
|
167
|
+
throw error;
|
|
212
168
|
}
|
|
213
|
-
|
|
214
|
-
|
|
169
|
+
}
|
|
170
|
+
async function detectOpenClaw() {
|
|
215
171
|
try {
|
|
216
|
-
await fs.
|
|
217
|
-
|
|
172
|
+
await fs.access(path.join(os.homedir(), ".openclaw"));
|
|
173
|
+
return true;
|
|
218
174
|
} catch {
|
|
175
|
+
return false;
|
|
219
176
|
}
|
|
220
177
|
}
|
|
221
178
|
async function main() {
|
|
222
|
-
console.log(
|
|
223
|
-
chalk.cyan.bold("\n ClawTrail Agent Skill Installer\n")
|
|
224
|
-
);
|
|
179
|
+
console.log(chalk.cyan.bold("\n ClawTrail Agent Installer\n"));
|
|
225
180
|
const program = new Command();
|
|
226
|
-
program.name("clawtrail-init").description("
|
|
181
|
+
program.name("clawtrail-init").description("Install ClawTrail skill files, configure heartbeat, and optionally register an agent").version("2.0.0").option("-d, --dir <path>", "Download directory for skill files", "./clawtrail-skills").option("-s, --staging", "Use staging environment", false).option("--name <name>", "Register agent with this name").option("--description <desc>", "Agent description (required with --name)").option("--bio <bio>", "Agent bio").option("--agent-type <type>", "Agent type (openclaw, custom, mcp-server, a2a-agent)", "openclaw").option("--framework <fw>", "Agent framework (e.g., langchain, autogen)").option("--skills <skills>", "Comma-separated skills (e.g., coding,research,dkg)").option("--capabilities <caps>", "Comma-separated capabilities (e.g., research,analysis)").option("--api-key <key>", "Existing API key (skip registration, just configure)").action(async (options) => {
|
|
227
182
|
const targetDir = path.resolve(process.cwd(), options.dir);
|
|
228
183
|
const staging = options.staging;
|
|
184
|
+
const env = staging ? "staging" : "production";
|
|
229
185
|
await downloadSkillFiles(targetDir, staging);
|
|
230
186
|
const hasOpenClaw = await detectOpenClaw();
|
|
187
|
+
let placedFiles = [];
|
|
231
188
|
if (hasOpenClaw) {
|
|
232
|
-
|
|
189
|
+
const spinner = ora("Placing files in OpenClaw directories...").start();
|
|
233
190
|
try {
|
|
234
|
-
await
|
|
235
|
-
|
|
236
|
-
|
|
191
|
+
placedFiles = await copyToOpenClawDirs(targetDir, staging);
|
|
192
|
+
spinner.succeed(chalk.green(`Placed ${placedFiles.length} files in OpenClaw`));
|
|
193
|
+
} catch (err) {
|
|
194
|
+
spinner.warn(chalk.yellow(`Could not place files: ${err.message}`));
|
|
237
195
|
}
|
|
238
196
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
245
|
-
|
|
197
|
+
let apiKey = options.apiKey || void 0;
|
|
198
|
+
let agentId;
|
|
199
|
+
let verificationCode;
|
|
200
|
+
if (options.name) {
|
|
201
|
+
if (!options.description) {
|
|
202
|
+
console.log(chalk.red("\n --description is required when using --name\n"));
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
const result = await registerAgent(
|
|
207
|
+
options.name.trim(),
|
|
208
|
+
options.description.trim(),
|
|
209
|
+
staging,
|
|
246
210
|
{
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
211
|
+
bio: options.bio?.trim(),
|
|
212
|
+
agentType: options.agentType,
|
|
213
|
+
framework: options.framework?.trim(),
|
|
214
|
+
skills: options.skills?.split(",").map((s) => s.trim()).filter(Boolean),
|
|
215
|
+
capabilities: options.capabilities?.split(",").map((s) => s.trim()).filter(Boolean)
|
|
251
216
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
217
|
+
);
|
|
218
|
+
apiKey = result.apiKey;
|
|
219
|
+
agentId = result.agentId;
|
|
220
|
+
verificationCode = result.verificationCode;
|
|
221
|
+
} catch {
|
|
257
222
|
}
|
|
258
223
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
]);
|
|
274
|
-
if (registrationChoice === "bot") {
|
|
275
|
-
console.log(chalk.green("\n Got it! Your bot will register itself.\n"));
|
|
276
|
-
console.log(chalk.gray(" Your bot can register using the SKILL.md instructions."));
|
|
277
|
-
console.log(chalk.gray(" It will call POST /api/agents/register with its own info."));
|
|
278
|
-
if (hasOpenClaw) {
|
|
279
|
-
console.log(chalk.gray(" The ClawTrail skill file has been placed in your OpenClaw workspace."));
|
|
280
|
-
console.log(chalk.gray(" Just start your bot \u2014 it will read the skill and register automatically.\n"));
|
|
281
|
-
} else {
|
|
282
|
-
console.log(chalk.gray(" Point your agent at the SKILL.md file to get started.\n"));
|
|
283
|
-
}
|
|
284
|
-
} else if (registrationChoice === "manual") {
|
|
285
|
-
const answers = await inquirer.prompt([
|
|
286
|
-
{
|
|
287
|
-
type: "input",
|
|
288
|
-
name: "name",
|
|
289
|
-
message: "Agent name:",
|
|
290
|
-
validate: (input) => {
|
|
291
|
-
if (!input.trim()) return "Name is required";
|
|
292
|
-
if (input.trim().length < 2) return "Name must be at least 2 characters";
|
|
293
|
-
if (input.trim().length > 100) return "Name must be under 100 characters";
|
|
294
|
-
return true;
|
|
295
|
-
}
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
type: "input",
|
|
299
|
-
name: "description",
|
|
300
|
-
message: "Agent description:",
|
|
301
|
-
validate: (input) => {
|
|
302
|
-
if (!input.trim()) return "Description is required";
|
|
303
|
-
if (input.trim().length < 10) return "Description must be at least 10 characters";
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
type: "input",
|
|
309
|
-
name: "bio",
|
|
310
|
-
message: "Short bio (optional):"
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
type: "list",
|
|
314
|
-
name: "agentType",
|
|
315
|
-
message: "Agent type:",
|
|
316
|
-
choices: [
|
|
317
|
-
{ name: "OpenClaw Agent", value: "openclaw" },
|
|
318
|
-
{ name: "Custom Agent", value: "custom" },
|
|
319
|
-
{ name: "MCP Server", value: "mcp-server" },
|
|
320
|
-
{ name: "A2A Agent", value: "a2a-agent" },
|
|
321
|
-
{ name: "ERC-8004 Agent", value: "erc8004" }
|
|
322
|
-
],
|
|
323
|
-
default: hasOpenClaw ? "openclaw" : "custom"
|
|
324
|
-
},
|
|
325
|
-
{
|
|
326
|
-
type: "input",
|
|
327
|
-
name: "framework",
|
|
328
|
-
message: "Framework (optional, e.g., langchain, autogen):"
|
|
329
|
-
},
|
|
330
|
-
{
|
|
331
|
-
type: "input",
|
|
332
|
-
name: "skills",
|
|
333
|
-
message: "Skills (optional, comma-separated, e.g., coding,research,dkg):"
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
type: "input",
|
|
337
|
-
name: "capabilities",
|
|
338
|
-
message: "Capabilities (optional, comma-separated, e.g., research,analysis,automation):"
|
|
339
|
-
}
|
|
340
|
-
]);
|
|
224
|
+
let ocConfig;
|
|
225
|
+
if (hasOpenClaw) {
|
|
226
|
+
const spinner = ora("Configuring OpenClaw heartbeat...").start();
|
|
227
|
+
try {
|
|
228
|
+
ocConfig = await configureOpenClaw(staging, apiKey);
|
|
229
|
+
spinner.succeed(chalk.green(`Heartbeat configured: ${chalk.cyan("every 30s")}`));
|
|
230
|
+
} catch (err) {
|
|
231
|
+
spinner.warn(chalk.yellow(`Config failed: ${err.message}`));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (apiKey) {
|
|
235
|
+
const envPath = path.join(process.cwd(), ".env");
|
|
236
|
+
try {
|
|
237
|
+
let existing = "";
|
|
341
238
|
try {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
capabilities: answers.capabilities ? answers.capabilities.split(",").map((s) => s.trim()).filter(Boolean) : ["general"]
|
|
351
|
-
},
|
|
352
|
-
staging
|
|
353
|
-
);
|
|
354
|
-
console.log(chalk.green("\n Registration Complete!\n"));
|
|
355
|
-
console.log(chalk.white("Agent ID: ") + chalk.cyan(agentId));
|
|
356
|
-
console.log(
|
|
357
|
-
chalk.white("Verification Code: ") + chalk.yellow(verificationCode)
|
|
358
|
-
);
|
|
359
|
-
console.log(
|
|
360
|
-
chalk.white("DKG Status: ") + chalk.yellow("pending \u2014 minting queued (~30s)")
|
|
361
|
-
);
|
|
362
|
-
console.log(
|
|
363
|
-
chalk.white("Status URL: ") + chalk.blue.underline(statusUrl)
|
|
364
|
-
);
|
|
365
|
-
await saveToEnv(apiKey);
|
|
366
|
-
console.log(chalk.yellow("\n IMPORTANT: Your API key has been saved to .env"));
|
|
367
|
-
console.log(chalk.yellow(" The verification code above will NOT be shown again.\n"));
|
|
368
|
-
if (hasOpenClaw && answers.agentType === "openclaw") {
|
|
369
|
-
const { configureOC } = await inquirer.prompt([
|
|
370
|
-
{
|
|
371
|
-
type: "confirm",
|
|
372
|
-
name: "configureOC",
|
|
373
|
-
message: "Auto-configure ClawTrail in OpenClaw (~/.openclaw/openclaw.json)?",
|
|
374
|
-
default: true
|
|
375
|
-
}
|
|
376
|
-
]);
|
|
377
|
-
if (configureOC) {
|
|
378
|
-
try {
|
|
379
|
-
await configureOpenClaw(apiKey, staging);
|
|
380
|
-
} catch (ocErr) {
|
|
381
|
-
console.log(chalk.yellow(` OpenClaw config failed: ${ocErr.message}`));
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
} catch (error) {
|
|
386
|
-
console.log(
|
|
387
|
-
chalk.red(`
|
|
388
|
-
Registration failed: ${error.message}
|
|
389
|
-
`)
|
|
390
|
-
);
|
|
391
|
-
console.log(
|
|
392
|
-
chalk.gray("You can register later via the ClawTrail API.\n")
|
|
393
|
-
);
|
|
239
|
+
existing = await fs.readFile(envPath, "utf-8");
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
if (!existing.includes("CLAWTRAIL_API_KEY")) {
|
|
243
|
+
await fs.appendFile(envPath, `
|
|
244
|
+
# ClawTrail API Key
|
|
245
|
+
CLAWTRAIL_API_KEY=${apiKey}
|
|
246
|
+
`);
|
|
394
247
|
}
|
|
248
|
+
} catch {
|
|
395
249
|
}
|
|
396
250
|
}
|
|
397
|
-
console.log(chalk.cyan.bold("\n
|
|
398
|
-
console.log(
|
|
399
|
-
|
|
400
|
-
)
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
chalk.white("
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
)
|
|
416
|
-
|
|
417
|
-
if (hasOpenClaw) {
|
|
418
|
-
console.log(
|
|
419
|
-
|
|
420
|
-
);
|
|
421
|
-
console.log(
|
|
422
|
-
chalk.white("6. ") + chalk.gray("(OpenClaw) Skill installed to OpenClaw skills directory")
|
|
423
|
-
);
|
|
251
|
+
console.log(chalk.cyan.bold("\n \u2500\u2500\u2500 Results \u2500\u2500\u2500\n"));
|
|
252
|
+
console.log(chalk.white(" Environment: ") + chalk.cyan(env));
|
|
253
|
+
console.log(chalk.white(" Skill files: ") + chalk.cyan(targetDir));
|
|
254
|
+
if (placedFiles.length > 0) {
|
|
255
|
+
for (const f of placedFiles) {
|
|
256
|
+
console.log(chalk.white(" Placed: ") + chalk.cyan(f));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (ocConfig) {
|
|
260
|
+
console.log(chalk.white(" Heartbeat: ") + chalk.green(ocConfig.heartbeat));
|
|
261
|
+
console.log(chalk.white(" Config: ") + chalk.cyan(ocConfig.configPath));
|
|
262
|
+
console.log(chalk.white(" API key: ") + chalk.cyan(ocConfig.hasApiKey ? "injected" : "not set (bot will self-register)"));
|
|
263
|
+
}
|
|
264
|
+
if (agentId) {
|
|
265
|
+
console.log(chalk.white(" Agent ID: ") + chalk.cyan(agentId));
|
|
266
|
+
}
|
|
267
|
+
if (verificationCode) {
|
|
268
|
+
console.log(chalk.white(" Verify code: ") + chalk.yellow(verificationCode));
|
|
269
|
+
console.log(chalk.gray(" (save this \u2014 shown only once)"));
|
|
270
|
+
}
|
|
271
|
+
if (!hasOpenClaw) {
|
|
272
|
+
console.log(chalk.gray("\n OpenClaw not detected \u2014 skill files saved to ") + chalk.cyan(targetDir));
|
|
273
|
+
console.log(chalk.gray(" Point your agent at SKILL.md to get started."));
|
|
424
274
|
}
|
|
425
|
-
const env = staging ? "staging" : "production";
|
|
426
275
|
const webUrl = staging ? "https://staging.clawtrail.ai" : "https://clawtrail.ai";
|
|
427
276
|
const apiUrl = staging ? "https://sapi.clawtrail.ai/ct/api" : "https://api.clawtrail.ai/ct/api";
|
|
428
|
-
console.log(chalk.cyan("\n
|
|
429
|
-
console.log(
|
|
430
|
-
|
|
431
|
-
);
|
|
432
|
-
console.log(
|
|
433
|
-
chalk.white("API: ") + chalk.blue.underline(apiUrl)
|
|
434
|
-
);
|
|
435
|
-
console.log(
|
|
436
|
-
chalk.white("Docs: ") + chalk.blue.underline("https://docs.clawtrail.ai")
|
|
437
|
-
);
|
|
438
|
-
console.log(
|
|
439
|
-
chalk.white("Environment: ") + chalk.cyan(env)
|
|
440
|
-
);
|
|
441
|
-
console.log(chalk.cyan("\n Happy building with ClawTrail!\n"));
|
|
277
|
+
console.log(chalk.cyan("\n \u2500\u2500\u2500 Links \u2500\u2500\u2500\n"));
|
|
278
|
+
console.log(chalk.white(" Web: ") + chalk.blue.underline(webUrl));
|
|
279
|
+
console.log(chalk.white(" API: ") + chalk.blue.underline(apiUrl));
|
|
280
|
+
console.log(chalk.white(" Docs: ") + chalk.blue.underline("https://docs.clawtrail.ai"));
|
|
281
|
+
console.log(chalk.cyan("\n Ready to go!\n"));
|
|
442
282
|
});
|
|
443
283
|
await program.parseAsync(process.argv);
|
|
444
284
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawtrail/init",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "CLI installer for ClawTrail AI agent skill files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,14 +23,12 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"commander": "^12.0.0",
|
|
26
|
-
"inquirer": "^9.2.15",
|
|
27
26
|
"chalk": "^5.3.0",
|
|
28
27
|
"ora": "^8.0.1",
|
|
29
28
|
"node-fetch": "^3.3.2",
|
|
30
29
|
"json5": "^2.2.3"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
|
-
"@types/inquirer": "^9.0.7",
|
|
34
32
|
"@types/node": "^22.0.0",
|
|
35
33
|
"tsup": "^8.5.0",
|
|
36
34
|
"typescript": "^5.7.2"
|