@botcord/botcord 0.1.3 → 0.1.4-beta.20260325025643

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/index.ts CHANGED
@@ -13,9 +13,11 @@ import { createPaymentTool } from "./src/tools/payment.js";
13
13
  import { createSubscriptionTool } from "./src/tools/subscription.js";
14
14
  import { createNotifyTool } from "./src/tools/notify.js";
15
15
  import { createBindTool } from "./src/tools/bind.js";
16
+ import { createRegisterTool } from "./src/tools/register.js";
16
17
  import { createHealthcheckCommand } from "./src/commands/healthcheck.js";
17
18
  import { createTokenCommand } from "./src/commands/token.js";
18
19
  import { createBindCommand } from "./src/commands/bind.js";
20
+ import { createEnvCommand } from "./src/commands/env.js";
19
21
  import { createRegisterCli } from "./src/commands/register.js";
20
22
  import {
21
23
  buildBotCordLoopRiskPrompt,
@@ -52,6 +54,7 @@ export default {
52
54
  api.registerTool(createSubscriptionTool() as any);
53
55
  api.registerTool(createNotifyTool() as any);
54
56
  api.registerTool(createBindTool() as any);
57
+ api.registerTool(createRegisterTool() as any);
55
58
 
56
59
  // Hooks
57
60
  api.on("after_tool_call", async (event: any, ctx: any) => {
@@ -90,6 +93,7 @@ export default {
90
93
  api.registerCommand(createHealthcheckCommand());
91
94
  api.registerCommand(createTokenCommand());
92
95
  api.registerCommand(createBindCommand());
96
+ api.registerCommand(createEnvCommand());
93
97
 
94
98
  // CLI
95
99
  const registerCli = createRegisterCli();
@@ -2,7 +2,7 @@
2
2
  "id": "botcord",
3
3
  "name": "BotCord",
4
4
  "description": "Secure agent-to-agent messaging via the BotCord A2A protocol (Ed25519 signed envelopes)",
5
- "version": "0.1.3",
5
+ "version": "0.1.4-beta.20260325025643",
6
6
  "channels": [
7
7
  "botcord"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botcord/botcord",
3
- "version": "0.1.3",
3
+ "version": "0.1.4-beta.20260325025643",
4
4
  "description": "OpenClaw channel plugin for BotCord A2A messaging protocol (Ed25519 signed envelopes)",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -0,0 +1,108 @@
1
+ /**
2
+ * /botcord_env — View or switch the BotCord Hub environment.
3
+ *
4
+ * Usage:
5
+ * /botcord_env — show current hub URL and environment
6
+ * /botcord_env stable — switch to stable (api.botcord.chat)
7
+ * /botcord_env beta — switch to beta (preview.botcord.chat)
8
+ * /botcord_env test — switch to test (test.botcord.chat)
9
+ * /botcord_env <url> — switch to a custom hub URL
10
+ *
11
+ * Changes are written to the credentials file. Restart gateway to take effect.
12
+ */
13
+ import { ENV_PRESETS } from "../constants.js";
14
+ import {
15
+ resolveAccountConfig,
16
+ isAccountConfigured,
17
+ } from "../config.js";
18
+ import {
19
+ loadStoredCredentials,
20
+ writeCredentialsFile,
21
+ } from "../credentials.js";
22
+ import { normalizeAndValidateHubUrl } from "../hub-url.js";
23
+ import { getConfig as getAppConfig } from "../runtime.js";
24
+
25
+ function resolveEnvLabel(hubUrl: string): string | null {
26
+ for (const [name, url] of Object.entries(ENV_PRESETS)) {
27
+ if (hubUrl === url) return name;
28
+ }
29
+ return null;
30
+ }
31
+
32
+ export function createEnvCommand() {
33
+ return {
34
+ name: "botcord_env",
35
+ description: "View or switch the BotCord Hub environment (stable/beta/test or custom URL).",
36
+ acceptsArgs: true,
37
+ requireAuth: true,
38
+ handler: async (ctx: any) => {
39
+ const cfg = getAppConfig();
40
+ if (!cfg) {
41
+ return { text: "[FAIL] No OpenClaw configuration available" };
42
+ }
43
+
44
+ const acct = resolveAccountConfig(cfg);
45
+ if (!isAccountConfigured(acct)) {
46
+ return { text: "[FAIL] BotCord is not fully configured (need hubUrl, agentId, keyId, privateKey)" };
47
+ }
48
+
49
+ const arg = (ctx.args || "").trim();
50
+
51
+ // ── No argument: show current environment ──
52
+ if (!arg) {
53
+ const current = acct.hubUrl || "(not set)";
54
+ const label = acct.hubUrl ? resolveEnvLabel(acct.hubUrl) : null;
55
+ const envDisplay = label ? ` (${label})` : "";
56
+ const presetList = Object.entries(ENV_PRESETS)
57
+ .map(([name, url]) => ` ${name} → ${url}`)
58
+ .join("\n");
59
+ return {
60
+ text: [
61
+ `Current hub: ${current}${envDisplay}`,
62
+ "",
63
+ "Available environments:",
64
+ presetList,
65
+ "",
66
+ "Usage: /botcord_env <stable|beta|test|URL>",
67
+ ].join("\n"),
68
+ };
69
+ }
70
+
71
+ // ── Resolve target URL ──
72
+ const targetUrl = ENV_PRESETS[arg] || arg;
73
+
74
+ let normalizedUrl: string;
75
+ try {
76
+ normalizedUrl = normalizeAndValidateHubUrl(targetUrl);
77
+ } catch (err: any) {
78
+ return { text: `[FAIL] Invalid hub URL: ${err.message}` };
79
+ }
80
+
81
+ // ── Check if already on this URL ──
82
+ if (acct.hubUrl === normalizedUrl) {
83
+ const label = resolveEnvLabel(normalizedUrl);
84
+ const envDisplay = label ? ` (${label})` : "";
85
+ return { text: `Already on ${normalizedUrl}${envDisplay}. No change needed.` };
86
+ }
87
+
88
+ // ── Write to credentials file ──
89
+ if (!acct.credentialsFile) {
90
+ return { text: "[FAIL] No credentials file configured — cannot persist hub URL change" };
91
+ }
92
+
93
+ try {
94
+ const creds = loadStoredCredentials(acct.credentialsFile);
95
+ creds.hubUrl = normalizedUrl;
96
+ writeCredentialsFile(acct.credentialsFile, creds);
97
+ } catch (err: any) {
98
+ return { text: `[FAIL] Could not update credentials file: ${err.message}` };
99
+ }
100
+
101
+ const label = resolveEnvLabel(normalizedUrl);
102
+ const envDisplay = label ? ` (${label})` : "";
103
+ return {
104
+ text: `[OK] Hub URL updated to ${normalizedUrl}${envDisplay}. Restart gateway to take effect.`,
105
+ };
106
+ },
107
+ };
108
+ }
package/src/constants.ts CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  export type ReleaseChannel = "stable" | "beta";
11
11
 
12
- export const RELEASE_CHANNEL: ReleaseChannel = "stable";
12
+ export const RELEASE_CHANNEL: ReleaseChannel = "beta";
13
13
 
14
14
  const HUB_URLS: Record<ReleaseChannel, string> = {
15
15
  stable: "https://api.botcord.chat",
@@ -17,3 +17,10 @@ const HUB_URLS: Record<ReleaseChannel, string> = {
17
17
  };
18
18
 
19
19
  export const DEFAULT_HUB = HUB_URLS[RELEASE_CHANNEL];
20
+
21
+ /** Named environment presets for /botcord_env. */
22
+ export const ENV_PRESETS: Record<string, string> = {
23
+ stable: "https://api.botcord.chat",
24
+ beta: "https://preview.botcord.chat",
25
+ test: "https://test.botcord.chat",
26
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * botcord_register — Register a new BotCord agent identity via tool call.
3
+ */
4
+ import { registerAgent } from "../commands/register.js";
5
+ import { getConfig as getAppConfig } from "../runtime.js";
6
+ import { DEFAULT_HUB } from "../constants.js";
7
+
8
+ export function createRegisterTool() {
9
+ return {
10
+ name: "botcord_register",
11
+ label: "Register Agent",
12
+ description:
13
+ "Register a new BotCord agent: generate an Ed25519 keypair, register with the Hub, and save credentials locally.",
14
+ parameters: {
15
+ type: "object" as const,
16
+ properties: {
17
+ name: {
18
+ type: "string" as const,
19
+ description: "Agent display name",
20
+ },
21
+ bio: {
22
+ type: "string" as const,
23
+ description: "Agent bio/description (optional)",
24
+ },
25
+ hub: {
26
+ type: "string" as const,
27
+ description: `Hub URL (defaults to ${DEFAULT_HUB})`,
28
+ },
29
+ new_identity: {
30
+ type: "boolean" as const,
31
+ description: "Generate a fresh keypair instead of reusing existing credentials (default false)",
32
+ },
33
+ },
34
+ required: ["name"],
35
+ },
36
+ execute: async (toolCallId: any, args: any, signal?: any, onUpdate?: any) => {
37
+ if (!args.name) {
38
+ return { error: "name is required" };
39
+ }
40
+
41
+ const cfg = getAppConfig();
42
+ if (!cfg) return { error: "No configuration available" };
43
+
44
+ try {
45
+ const result = await registerAgent({
46
+ name: args.name,
47
+ bio: args.bio || "",
48
+ hub: args.hub || DEFAULT_HUB,
49
+ config: cfg,
50
+ newIdentity: args.new_identity ?? false,
51
+ });
52
+ return {
53
+ ok: true,
54
+ agent_id: result.agentId,
55
+ key_id: result.keyId,
56
+ display_name: result.displayName,
57
+ hub: result.hub,
58
+ credentials_file: result.credentialsFile,
59
+ claim_url: result.claimUrl,
60
+ note: "Restart OpenClaw to activate: openclaw gateway restart",
61
+ };
62
+ } catch (err: any) {
63
+ return { error: `Registration failed: ${err.message}` };
64
+ }
65
+ },
66
+ };
67
+ }