@clawtrail/init 2.7.1 → 2.10.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 +166 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18,11 +18,13 @@ import JSON5 from "json5";
|
|
|
18
18
|
import { execSync } from "child_process";
|
|
19
19
|
var SKILL_FILES = {
|
|
20
20
|
SKILL: "https://api.clawtrail.ai/ct/api/skill/clawtrail.md",
|
|
21
|
-
HEARTBEAT: "https://api.clawtrail.ai/ct/api/skill/HEARTBEAT.md"
|
|
21
|
+
HEARTBEAT: "https://api.clawtrail.ai/ct/api/skill/HEARTBEAT.md",
|
|
22
|
+
MESSAGING: "https://api.clawtrail.ai/ct/api/skill/MESSAGING.md"
|
|
22
23
|
};
|
|
23
24
|
var STAGING_SKILL_FILES = {
|
|
24
25
|
SKILL: "https://sapi.clawtrail.ai/ct/api/skill/clawtrail.md",
|
|
25
|
-
HEARTBEAT: "https://sapi.clawtrail.ai/ct/api/skill/HEARTBEAT.md"
|
|
26
|
+
HEARTBEAT: "https://sapi.clawtrail.ai/ct/api/skill/HEARTBEAT.md",
|
|
27
|
+
MESSAGING: "https://sapi.clawtrail.ai/ct/api/skill/MESSAGING.md"
|
|
26
28
|
};
|
|
27
29
|
var MAX_RETRIES = 3;
|
|
28
30
|
var RETRY_DELAYS = [1e3, 3e3, 5e3];
|
|
@@ -69,6 +71,11 @@ async function downloadSkillFiles(targetDir, staging = false) {
|
|
|
69
71
|
url: files.HEARTBEAT,
|
|
70
72
|
dest: path.join(targetDir, "HEARTBEAT.md"),
|
|
71
73
|
name: "HEARTBEAT.md"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
url: files.MESSAGING,
|
|
77
|
+
dest: path.join(targetDir, "MESSAGING.md"),
|
|
78
|
+
name: "MESSAGING.md"
|
|
72
79
|
}
|
|
73
80
|
];
|
|
74
81
|
const results = await Promise.allSettled(
|
|
@@ -97,7 +104,53 @@ async function downloadSkillFiles(targetDir, staging = false) {
|
|
|
97
104
|
}
|
|
98
105
|
return { succeeded, failed };
|
|
99
106
|
}
|
|
100
|
-
async function
|
|
107
|
+
async function detectOpenClawAgents() {
|
|
108
|
+
const openclawDir = path.join(os.homedir(), ".openclaw");
|
|
109
|
+
const agents = [];
|
|
110
|
+
try {
|
|
111
|
+
const configPath = path.join(openclawDir, "openclaw.json");
|
|
112
|
+
const raw = await fs.readFile(configPath, "utf-8");
|
|
113
|
+
const config = JSON5.parse(raw);
|
|
114
|
+
if (config.agents?.list && Array.isArray(config.agents.list)) {
|
|
115
|
+
for (const agent of config.agents.list) {
|
|
116
|
+
if (agent.id) {
|
|
117
|
+
agents.push({
|
|
118
|
+
id: agent.id,
|
|
119
|
+
workspace: agent.workspace || path.join(openclawDir, `workspace-${agent.id}`),
|
|
120
|
+
isDefault: !!agent.default
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
if (agents.length === 0) {
|
|
128
|
+
try {
|
|
129
|
+
const agentsDir = path.join(openclawDir, "agents");
|
|
130
|
+
const entries = await fs.readdir(agentsDir, { withFileTypes: true });
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
if (entry.isDirectory()) {
|
|
133
|
+
const id = entry.name;
|
|
134
|
+
agents.push({
|
|
135
|
+
id,
|
|
136
|
+
workspace: id === "main" ? path.join(openclawDir, "workspace") : path.join(openclawDir, `workspace-${id}`),
|
|
137
|
+
isDefault: id === "main"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (agents.length === 0) {
|
|
145
|
+
agents.push({
|
|
146
|
+
id: "main",
|
|
147
|
+
workspace: path.join(openclawDir, "workspace"),
|
|
148
|
+
isDefault: true
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return agents;
|
|
152
|
+
}
|
|
153
|
+
async function installContextGraph(staging, agentId, apiKey, trackedAgents) {
|
|
101
154
|
const spinner = ora("Setting up context-graph provenance...").start();
|
|
102
155
|
const openclawDir = path.join(os.homedir(), ".openclaw");
|
|
103
156
|
const extensionsDir = path.join(openclawDir, "extensions", "context-graph");
|
|
@@ -117,17 +170,29 @@ async function installContextGraph(staging, agentId, apiKey) {
|
|
|
117
170
|
config.plugins ??= {};
|
|
118
171
|
config.plugins.entries ??= {};
|
|
119
172
|
const cgRoot = path.join(openclawDir, "workspace", ".context-graph");
|
|
173
|
+
const cgConfig = {
|
|
174
|
+
submitUrl: `${apiUrl}/context-graph/submit`,
|
|
175
|
+
autoSubmit: true,
|
|
176
|
+
detectHttp: true,
|
|
177
|
+
environment: staging ? "staging" : "production",
|
|
178
|
+
contextGraphRoot: cgRoot
|
|
179
|
+
};
|
|
180
|
+
if (trackedAgents && trackedAgents.length > 0) {
|
|
181
|
+
const agentsMap = {};
|
|
182
|
+
for (const ta of trackedAgents) {
|
|
183
|
+
agentsMap[ta.openclawId] = {
|
|
184
|
+
clawtrailId: ta.clawtrailId,
|
|
185
|
+
apiKey: ta.apiKey
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
cgConfig.agents = agentsMap;
|
|
189
|
+
} else {
|
|
190
|
+
cgConfig.agentId = agentId || void 0;
|
|
191
|
+
cgConfig.apiKey = apiKey || void 0;
|
|
192
|
+
}
|
|
120
193
|
config.plugins.entries["context-graph"] = {
|
|
121
194
|
enabled: true,
|
|
122
|
-
config:
|
|
123
|
-
submitUrl: `${apiUrl}/context-graph/submit`,
|
|
124
|
-
agentId: agentId || void 0,
|
|
125
|
-
apiKey: apiKey || void 0,
|
|
126
|
-
autoSubmit: true,
|
|
127
|
-
detectHttp: true,
|
|
128
|
-
environment: staging ? "staging" : "production",
|
|
129
|
-
contextGraphRoot: cgRoot
|
|
130
|
-
}
|
|
195
|
+
config: cgConfig
|
|
131
196
|
};
|
|
132
197
|
await fs.writeFile(
|
|
133
198
|
openclawConfigPath,
|
|
@@ -141,10 +206,10 @@ async function installContextGraph(staging, agentId, apiKey) {
|
|
|
141
206
|
try {
|
|
142
207
|
execSync("openclaw --version", { stdio: "pipe", timeout: 5e3 });
|
|
143
208
|
try {
|
|
144
|
-
execSync(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
);
|
|
209
|
+
execSync("openclaw plugins install @clawtrail/context-graph-openclaw", {
|
|
210
|
+
stdio: "pipe",
|
|
211
|
+
timeout: 12e4
|
|
212
|
+
});
|
|
148
213
|
packagesInstalled = true;
|
|
149
214
|
} catch (err) {
|
|
150
215
|
installError = err.stderr?.toString().trim() || err.stdout?.toString().trim() || err.message || "Unknown error";
|
|
@@ -408,7 +473,9 @@ async function handleUninstall(staging) {
|
|
|
408
473
|
const spinner1 = ora("Removing skill files...").start();
|
|
409
474
|
const filesToRemove = [
|
|
410
475
|
path.join(openclawDir, "workspace", "HEARTBEAT.md"),
|
|
411
|
-
path.join(openclawDir, "
|
|
476
|
+
path.join(openclawDir, "workspace", "MESSAGING.md"),
|
|
477
|
+
path.join(openclawDir, "skills", skillFolder, "SKILL.md"),
|
|
478
|
+
path.join(os.homedir(), ".config", "clawtrail", "credentials.json")
|
|
412
479
|
];
|
|
413
480
|
for (const filePath of filesToRemove) {
|
|
414
481
|
try {
|
|
@@ -559,7 +626,7 @@ async function main() {
|
|
|
559
626
|
const program = new Command();
|
|
560
627
|
program.name("clawtrail-init").description(
|
|
561
628
|
"Install ClawTrail skill files, configure heartbeat, and optionally register an agent"
|
|
562
|
-
).version("2.
|
|
629
|
+
).version("2.10.0").option(
|
|
563
630
|
"-d, --dir <path>",
|
|
564
631
|
"Download directory for skill files",
|
|
565
632
|
"./clawtrail-skills"
|
|
@@ -579,6 +646,9 @@ async function main() {
|
|
|
579
646
|
).option("--no-restart", "Skip gateway restart after updating files").option(
|
|
580
647
|
"--no-context-graph",
|
|
581
648
|
"Skip context-graph provenance tracking installation"
|
|
649
|
+
).option(
|
|
650
|
+
"--agent <id>",
|
|
651
|
+
"Track only this OpenClaw agent ID for context-graph (multi-agent mode)"
|
|
582
652
|
).option(
|
|
583
653
|
"--uninstall",
|
|
584
654
|
"Remove ClawTrail skill files, config, and restart gateway"
|
|
@@ -609,6 +679,11 @@ async function main() {
|
|
|
609
679
|
dest: path.join(workspaceDir, "HEARTBEAT.md"),
|
|
610
680
|
label: `~/.openclaw/workspace/HEARTBEAT.md`
|
|
611
681
|
},
|
|
682
|
+
{
|
|
683
|
+
url: files.MESSAGING,
|
|
684
|
+
dest: path.join(workspaceDir, "MESSAGING.md"),
|
|
685
|
+
label: `~/.openclaw/workspace/MESSAGING.md`
|
|
686
|
+
},
|
|
612
687
|
{
|
|
613
688
|
url: files.SKILL,
|
|
614
689
|
dest: path.join(skillsDir, "SKILL.md"),
|
|
@@ -674,6 +749,32 @@ async function main() {
|
|
|
674
749
|
} catch {
|
|
675
750
|
}
|
|
676
751
|
}
|
|
752
|
+
if (agentId && apiKey) {
|
|
753
|
+
try {
|
|
754
|
+
const credDir = path.join(os.homedir(), ".config", "clawtrail");
|
|
755
|
+
const credPath = path.join(credDir, "credentials.json");
|
|
756
|
+
await ensureDirectory(credDir);
|
|
757
|
+
let exists = false;
|
|
758
|
+
try {
|
|
759
|
+
await fs.access(credPath);
|
|
760
|
+
exists = true;
|
|
761
|
+
} catch {
|
|
762
|
+
}
|
|
763
|
+
if (!exists) {
|
|
764
|
+
const creds = {
|
|
765
|
+
agentId,
|
|
766
|
+
apiKey,
|
|
767
|
+
verificationCode: verificationCode || void 0,
|
|
768
|
+
environment: env
|
|
769
|
+
};
|
|
770
|
+
await fs.writeFile(credPath, JSON.stringify(creds, null, 2), {
|
|
771
|
+
encoding: "utf-8",
|
|
772
|
+
mode: 384
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
} catch {
|
|
776
|
+
}
|
|
777
|
+
}
|
|
677
778
|
let ocConfig;
|
|
678
779
|
if (hasOpenClaw) {
|
|
679
780
|
const spinner = ora("Configuring OpenClaw heartbeat...").start();
|
|
@@ -687,14 +788,53 @@ async function main() {
|
|
|
687
788
|
}
|
|
688
789
|
}
|
|
689
790
|
let cgResult;
|
|
690
|
-
|
|
791
|
+
const shouldInstallCG = options.contextGraph !== false && staging;
|
|
792
|
+
if (shouldInstallCG) {
|
|
793
|
+
const detectedAgents = await detectOpenClawAgents();
|
|
794
|
+
const targetAgentId = options.agent;
|
|
795
|
+
if (detectedAgents.length > 1) {
|
|
796
|
+
console.log(
|
|
797
|
+
chalk.cyan("\n Detected OpenClaw agents:")
|
|
798
|
+
);
|
|
799
|
+
for (const a of detectedAgents) {
|
|
800
|
+
const marker = targetAgentId === a.id ? chalk.green(" \u2190 tracking") : a.isDefault ? chalk.gray(" (default)") : "";
|
|
801
|
+
console.log(chalk.white(` \u2022 ${a.id}${marker}`));
|
|
802
|
+
}
|
|
803
|
+
if (!targetAgentId) {
|
|
804
|
+
console.log(
|
|
805
|
+
chalk.gray(
|
|
806
|
+
"\n Tip: Use --agent <id> to track only a specific agent\n"
|
|
807
|
+
)
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
691
811
|
try {
|
|
692
|
-
|
|
812
|
+
let trackedAgents;
|
|
813
|
+
if (targetAgentId && agentId && apiKey) {
|
|
814
|
+
trackedAgents = [
|
|
815
|
+
{
|
|
816
|
+
openclawId: targetAgentId,
|
|
817
|
+
clawtrailId: agentId,
|
|
818
|
+
apiKey
|
|
819
|
+
}
|
|
820
|
+
];
|
|
821
|
+
}
|
|
822
|
+
cgResult = await installContextGraph(
|
|
823
|
+
staging,
|
|
824
|
+
agentId,
|
|
825
|
+
apiKey,
|
|
826
|
+
trackedAgents
|
|
827
|
+
);
|
|
828
|
+
if (targetAgentId) {
|
|
829
|
+
console.log(
|
|
830
|
+
chalk.green(
|
|
831
|
+
` Context-graph tracking: only agent "${targetAgentId}"`
|
|
832
|
+
)
|
|
833
|
+
);
|
|
834
|
+
}
|
|
693
835
|
} catch (err) {
|
|
694
836
|
console.log(
|
|
695
|
-
chalk.yellow(
|
|
696
|
-
` Context-graph setup skipped: ${err.message}`
|
|
697
|
-
)
|
|
837
|
+
chalk.yellow(` Context-graph setup skipped: ${err.message}`)
|
|
698
838
|
);
|
|
699
839
|
}
|
|
700
840
|
}
|
|
@@ -752,6 +892,9 @@ CLAWTRAIL_API_KEY=${apiKey}
|
|
|
752
892
|
}
|
|
753
893
|
if (agentId) {
|
|
754
894
|
console.log(chalk.white(" Agent ID: ") + chalk.cyan(agentId));
|
|
895
|
+
console.log(
|
|
896
|
+
chalk.white(" Credentials: ") + chalk.cyan("~/.config/clawtrail/credentials.json")
|
|
897
|
+
);
|
|
755
898
|
}
|
|
756
899
|
if (verificationCode) {
|
|
757
900
|
console.log(
|