@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.
Files changed (2) hide show
  1. package/dist/index.js +166 -23
  2. 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 installContextGraph(staging, agentId, apiKey) {
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
- "openclaw plugins install @clawtrail/context-graph-openclaw",
146
- { stdio: "pipe", timeout: 12e4 }
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, "skills", skillFolder, "SKILL.md")
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.7.0").option(
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
- if (options.contextGraph !== false) {
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
- cgResult = await installContextGraph(staging, agentId, apiKey);
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(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawtrail/init",
3
- "version": "2.7.1",
3
+ "version": "2.10.0",
4
4
  "description": "CLI installer for ClawTrail AI agent skill files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {