@annals/agent-mesh 0.14.0 → 0.15.1

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 +310 -185
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1007,7 +1007,6 @@ var SENSITIVE_PATHS = [
1007
1007
  // contains ah_ platform token
1008
1008
  "~/.agent-mesh/pids",
1009
1009
  "~/.agent-mesh/logs",
1010
- "~/.codex",
1011
1010
  // Package manager tokens
1012
1011
  "~/.npmrc",
1013
1012
  "~/.yarnrc",
@@ -1027,16 +1026,6 @@ var SANDBOX_PRESETS = {
1027
1026
  allowWrite: [".", "/tmp"],
1028
1027
  denyWrite: [".env", ".env.*"]
1029
1028
  },
1030
- codex: {
1031
- denyRead: [...SENSITIVE_PATHS],
1032
- allowWrite: [".", "/tmp"],
1033
- denyWrite: [".env", ".env.*"]
1034
- },
1035
- gemini: {
1036
- denyRead: [...SENSITIVE_PATHS],
1037
- allowWrite: [".", "/tmp"],
1038
- denyWrite: [".env", ".env.*"]
1039
- },
1040
1029
  openclaw: {
1041
1030
  denyRead: [...SENSITIVE_PATHS],
1042
1031
  allowWrite: ["/tmp"],
@@ -1748,34 +1737,6 @@ var ClaudeAdapter = class extends AgentAdapter {
1748
1737
  }
1749
1738
  };
1750
1739
 
1751
- // src/adapters/codex.ts
1752
- var CodexAdapter = class extends AgentAdapter {
1753
- type = "codex";
1754
- displayName = "Codex CLI";
1755
- async isAvailable() {
1756
- return false;
1757
- }
1758
- createSession(_id, _config) {
1759
- throw new Error("Codex adapter not yet implemented");
1760
- }
1761
- destroySession(_id) {
1762
- }
1763
- };
1764
-
1765
- // src/adapters/gemini.ts
1766
- var GeminiAdapter = class extends AgentAdapter {
1767
- type = "gemini";
1768
- displayName = "Gemini CLI";
1769
- async isAvailable() {
1770
- return false;
1771
- }
1772
- createSession(_id, _config) {
1773
- throw new Error("Gemini adapter not yet implemented");
1774
- }
1775
- destroySession(_id) {
1776
- }
1777
- };
1778
-
1779
1740
  // src/commands/connect.ts
1780
1741
  var DEFAULT_BRIDGE_URL = "wss://bridge.agents.hot/ws";
1781
1742
  function logWorkspaceHint(slug, projectPath) {
@@ -1791,12 +1752,8 @@ function createAdapter(type, config) {
1791
1752
  return new OpenClawAdapter(config);
1792
1753
  case "claude":
1793
1754
  return new ClaudeAdapter(config);
1794
- case "codex":
1795
- return new CodexAdapter(config);
1796
- case "gemini":
1797
- return new GeminiAdapter(config);
1798
1755
  default:
1799
- throw new Error(`Unknown agent type: ${type}. Supported: openclaw, claude, codex, gemini`);
1756
+ throw new Error(`Unknown agent type: ${type}. Supported: openclaw, claude`);
1800
1757
  }
1801
1758
  }
1802
1759
  function registerConnectCommand(program2) {
@@ -1962,11 +1919,7 @@ function registerConnectCommand(program2) {
1962
1919
  log.info(`Checking ${adapter.displayName} availability...`);
1963
1920
  const available = await adapter.isAvailable();
1964
1921
  if (!available) {
1965
- if (agentType === "codex" || agentType === "gemini") {
1966
- log.error(`${adapter.displayName} adapter is not yet implemented. Supported adapters: openclaw, claude`);
1967
- } else {
1968
- log.error(`${adapter.displayName} is not available. Make sure it is installed and running.`);
1969
- }
1922
+ log.error(`${adapter.displayName} is not available. Make sure it is installed and running.`);
1970
1923
  process.exit(1);
1971
1924
  }
1972
1925
  log.success(`${adapter.displayName} is available`);
@@ -2208,7 +2161,7 @@ function registerStatusCommand(program2) {
2208
2161
  }
2209
2162
  console.log("\nTo connect an agent, run:");
2210
2163
  console.log(" agent-mesh connect <type> --agent-id <id>");
2211
- console.log("\nSupported types: openclaw, claude, codex, gemini");
2164
+ console.log("\nSupported types: openclaw, claude");
2212
2165
  });
2213
2166
  }
2214
2167
 
@@ -2943,18 +2896,18 @@ async function asyncChat(opts) {
2943
2896
  }
2944
2897
  throw new Error(msg);
2945
2898
  }
2946
- const { task_id, status, error_message, error_code } = await res.json();
2899
+ const { request_id, status, error_message, error_code } = await res.json();
2947
2900
  if (status === "failed") {
2948
2901
  throw new Error(`Task failed: ${error_message || error_code}`);
2949
2902
  }
2950
- process.stderr.write(`${GRAY}[async] task=${task_id.slice(0, 8)}... polling${RESET}`);
2903
+ process.stderr.write(`${GRAY}[async] request=${request_id.slice(0, 8)}... polling${RESET}`);
2951
2904
  const maxWait = 5 * 60 * 1e3;
2952
2905
  const pollInterval = 2e3;
2953
2906
  const startTime = Date.now();
2954
2907
  while (Date.now() - startTime < maxWait) {
2955
2908
  if (opts.signal?.aborted) throw new Error("Aborted");
2956
2909
  await sleep4(pollInterval);
2957
- const pollRes = await fetch(`${opts.baseUrl}/api/tasks/${task_id}`, {
2910
+ const pollRes = await fetch(`${opts.baseUrl}/api/agents/${opts.agentId}/task-status/${request_id}`, {
2958
2911
  headers: { Authorization: `Bearer ${opts.token}` },
2959
2912
  signal: opts.signal
2960
2913
  });
@@ -2980,7 +2933,7 @@ async function asyncChat(opts) {
2980
2933
  throw new Error("Task timed out waiting for result");
2981
2934
  }
2982
2935
  async function streamChat(opts) {
2983
- if ((opts.mode ?? "async") === "async") {
2936
+ if (opts.mode === "async") {
2984
2937
  return asyncChat(opts);
2985
2938
  }
2986
2939
  const res = await fetch(`${opts.baseUrl}/api/agents/${opts.agentId}/chat`, {
@@ -3083,7 +3036,7 @@ ${"\x1B[31m"}Error: ${event.errorText}${RESET}
3083
3036
  }
3084
3037
  }
3085
3038
  function registerChatCommand(program2) {
3086
- program2.command("chat <agent> [message]").description("Chat with an agent through the platform (for debugging)").option("--no-thinking", "Hide thinking/reasoning output").option("--stream", "Force SSE streaming mode (default is async)").option("--base-url <url>", "Platform base URL", DEFAULT_BASE_URL3).action(async (agentInput, inlineMessage, opts) => {
3039
+ program2.command("chat <agent> [message]").description("Chat with an agent through the platform (for debugging)").option("--no-thinking", "Hide thinking/reasoning output").option("--async", "Use async polling mode (default is stream)").option("--base-url <url>", "Platform base URL", DEFAULT_BASE_URL3).action(async (agentInput, inlineMessage, opts) => {
3087
3040
  const token = loadToken();
3088
3041
  if (!token) {
3089
3042
  log.error("Not authenticated. Run `agent-mesh login` first.");
@@ -3100,7 +3053,7 @@ function registerChatCommand(program2) {
3100
3053
  log.error(err.message);
3101
3054
  process.exit(1);
3102
3055
  }
3103
- const mode = opts.stream ? "stream" : "async";
3056
+ const mode = opts.async ? "async" : "stream";
3104
3057
  if (inlineMessage) {
3105
3058
  log.info(`Chatting with ${BOLD}${agentName}${RESET} (${mode})`);
3106
3059
  try {
@@ -3853,6 +3806,9 @@ function registerDiscoverCommand(program2) {
3853
3806
  // src/commands/call.ts
3854
3807
  import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
3855
3808
  var DEFAULT_BASE_URL4 = "https://agents.hot";
3809
+ function sleep5(ms) {
3810
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
3811
+ }
3856
3812
  function handleError2(err) {
3857
3813
  if (err instanceof PlatformApiError) {
3858
3814
  log.error(err.message);
@@ -3861,8 +3817,228 @@ function handleError2(err) {
3861
3817
  }
3862
3818
  process.exit(1);
3863
3819
  }
3820
+ async function asyncCall(opts) {
3821
+ const selfAgentId = process.env.AGENT_BRIDGE_AGENT_ID;
3822
+ const res = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/call`, {
3823
+ method: "POST",
3824
+ headers: {
3825
+ Authorization: `Bearer ${opts.token}`,
3826
+ "Content-Type": "application/json",
3827
+ ...selfAgentId ? { "X-Caller-Agent-Id": selfAgentId } : {}
3828
+ },
3829
+ body: JSON.stringify({ task_description: opts.taskDescription, mode: "async" }),
3830
+ signal: opts.signal
3831
+ });
3832
+ if (!res.ok) {
3833
+ let msg = `HTTP ${res.status}`;
3834
+ let errorCode = "";
3835
+ try {
3836
+ const body = await res.json();
3837
+ errorCode = body.error || "";
3838
+ msg = body.message || body.error || msg;
3839
+ } catch {
3840
+ }
3841
+ if (errorCode === "subscription_required") {
3842
+ log.error("This is a private agent.");
3843
+ console.error(` Subscribe first: agent-mesh subscribe <author-login>`);
3844
+ } else {
3845
+ log.error(msg);
3846
+ }
3847
+ process.exit(1);
3848
+ }
3849
+ const { request_id, call_id, status, error_message, error_code } = await res.json();
3850
+ if (status === "failed") {
3851
+ log.error(`Call failed: ${error_message || error_code}`);
3852
+ process.exit(1);
3853
+ }
3854
+ if (!opts.json) {
3855
+ process.stderr.write(`${GRAY}[async] call=${call_id.slice(0, 8)}... request=${request_id.slice(0, 8)}... polling${RESET}`);
3856
+ }
3857
+ const pollInterval = 2e3;
3858
+ const startTime = Date.now();
3859
+ while (Date.now() - startTime < opts.timeoutMs) {
3860
+ if (opts.signal?.aborted) {
3861
+ log.error("Aborted");
3862
+ process.exit(1);
3863
+ }
3864
+ await sleep5(pollInterval);
3865
+ const pollRes = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/task-status/${request_id}`, {
3866
+ headers: { Authorization: `Bearer ${opts.token}` },
3867
+ signal: opts.signal
3868
+ });
3869
+ if (!pollRes.ok) {
3870
+ log.error(`Poll failed: HTTP ${pollRes.status}`);
3871
+ process.exit(1);
3872
+ }
3873
+ const task = await pollRes.json();
3874
+ if (task.status === "completed") {
3875
+ if (!opts.json) {
3876
+ process.stderr.write(` done
3877
+ `);
3878
+ }
3879
+ const result = task.result || "";
3880
+ if (opts.json) {
3881
+ console.log(JSON.stringify({ call_id, request_id, status: "completed", result }));
3882
+ } else {
3883
+ process.stdout.write(result + "\n");
3884
+ }
3885
+ if (opts.outputFile && result) {
3886
+ writeFileSync2(opts.outputFile, result);
3887
+ if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
3888
+ }
3889
+ return;
3890
+ }
3891
+ if (task.status === "failed") {
3892
+ if (!opts.json) {
3893
+ process.stderr.write(` failed
3894
+ `);
3895
+ }
3896
+ log.error(`Call failed: ${task.error_message || task.error_code}`);
3897
+ process.exit(1);
3898
+ }
3899
+ if (!opts.json) {
3900
+ process.stderr.write(".");
3901
+ }
3902
+ }
3903
+ if (!opts.json) {
3904
+ process.stderr.write(` timeout
3905
+ `);
3906
+ }
3907
+ log.error("Call timed out waiting for result");
3908
+ process.exit(1);
3909
+ }
3910
+ async function streamCall(opts) {
3911
+ const selfAgentId = process.env.AGENT_BRIDGE_AGENT_ID;
3912
+ const res = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/call`, {
3913
+ method: "POST",
3914
+ headers: {
3915
+ Authorization: `Bearer ${opts.token}`,
3916
+ "Content-Type": "application/json",
3917
+ Accept: "text/event-stream",
3918
+ ...selfAgentId ? { "X-Caller-Agent-Id": selfAgentId } : {}
3919
+ },
3920
+ body: JSON.stringify({ task_description: opts.taskDescription }),
3921
+ signal: opts.signal
3922
+ });
3923
+ if (!res.ok) {
3924
+ let msg = `HTTP ${res.status}`;
3925
+ let errorCode = "";
3926
+ try {
3927
+ const body = await res.json();
3928
+ errorCode = body.error || "";
3929
+ msg = body.message || body.error || msg;
3930
+ } catch {
3931
+ }
3932
+ if (errorCode === "subscription_required") {
3933
+ log.error("This is a private agent.");
3934
+ console.error(` Subscribe first: agent-mesh subscribe <author-login>`);
3935
+ } else {
3936
+ log.error(msg);
3937
+ }
3938
+ process.exit(1);
3939
+ }
3940
+ const contentType = res.headers.get("Content-Type") || "";
3941
+ if (contentType.includes("application/json")) {
3942
+ const result = await res.json();
3943
+ if (opts.json) {
3944
+ console.log(JSON.stringify(result));
3945
+ } else {
3946
+ console.log("");
3947
+ log.success(`Call created for ${BOLD}${opts.name}${RESET}`);
3948
+ console.log(` ${GRAY}Call ID${RESET} ${result.call_id}`);
3949
+ console.log(` ${GRAY}Status${RESET} ${result.status}`);
3950
+ console.log(` ${GRAY}Created${RESET} ${result.created_at}`);
3951
+ console.log("");
3952
+ }
3953
+ return;
3954
+ }
3955
+ if (!res.body) {
3956
+ log.error("Empty response body");
3957
+ process.exit(1);
3958
+ }
3959
+ if (!opts.json) {
3960
+ log.info(`Calling ${BOLD}${opts.name}${RESET}...`);
3961
+ console.log("");
3962
+ }
3963
+ const reader = res.body.getReader();
3964
+ const decoder = new TextDecoder();
3965
+ let buffer = "";
3966
+ let outputBuffer = "";
3967
+ let inThinkingBlock = false;
3968
+ while (true) {
3969
+ const { done, value } = await reader.read();
3970
+ if (done) break;
3971
+ const chunk = decoder.decode(value, { stream: true });
3972
+ const parsed = parseSseChunk(chunk, buffer);
3973
+ buffer = parsed.carry;
3974
+ for (const data of parsed.events) {
3975
+ if (data === "[DONE]") continue;
3976
+ try {
3977
+ const event = JSON.parse(data);
3978
+ if (opts.json) {
3979
+ console.log(JSON.stringify(event));
3980
+ } else {
3981
+ if (event.type === "chunk" && event.delta) {
3982
+ process.stdout.write(event.delta);
3983
+ if (!event.kind || event.kind === "text") {
3984
+ const delta = event.delta;
3985
+ if (delta.startsWith("{") && delta.includes('"type":')) {
3986
+ if (delta.includes('"type":"thinking"') && delta.includes("content_block_start")) {
3987
+ inThinkingBlock = true;
3988
+ } else if (delta.includes('"type":"text"') && delta.includes("content_block_start")) {
3989
+ inThinkingBlock = false;
3990
+ }
3991
+ } else if (!inThinkingBlock) {
3992
+ outputBuffer += delta;
3993
+ }
3994
+ }
3995
+ } else if (event.type === "done" && event.attachments?.length) {
3996
+ console.log("");
3997
+ for (const att of event.attachments) {
3998
+ log.info(` ${GRAY}File:${RESET} ${att.name} ${GRAY}${att.url}${RESET}`);
3999
+ }
4000
+ } else if (event.type === "error") {
4001
+ process.stderr.write(`
4002
+ Error: ${event.message}
4003
+ `);
4004
+ }
4005
+ }
4006
+ } catch {
4007
+ }
4008
+ }
4009
+ }
4010
+ if (buffer.trim()) {
4011
+ const parsed = parseSseChunk("\n\n", buffer);
4012
+ for (const data of parsed.events) {
4013
+ if (data === "[DONE]") continue;
4014
+ try {
4015
+ const event = JSON.parse(data);
4016
+ if (opts.json) {
4017
+ console.log(JSON.stringify(event));
4018
+ } else if (event.type === "chunk" && event.delta) {
4019
+ process.stdout.write(event.delta);
4020
+ if (!event.kind || event.kind === "text") {
4021
+ const delta = event.delta;
4022
+ if (!(delta.startsWith("{") && delta.includes('"type":')) && !inThinkingBlock) {
4023
+ outputBuffer += delta;
4024
+ }
4025
+ }
4026
+ }
4027
+ } catch {
4028
+ }
4029
+ }
4030
+ }
4031
+ if (opts.outputFile && outputBuffer) {
4032
+ writeFileSync2(opts.outputFile, outputBuffer);
4033
+ if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
4034
+ }
4035
+ if (!opts.json) {
4036
+ console.log("\n");
4037
+ log.success("Call completed");
4038
+ }
4039
+ }
3864
4040
  function registerCallCommand(program2) {
3865
- program2.command("call <agent>").description("Call an agent on the A2A network").requiredOption("--task <description>", "Task description").option("--input-file <path>", "Read file and append to task description").option("--output-file <path>", "Save response text to file").option("--json", "Output JSONL events").option("--timeout <seconds>", "Timeout in seconds", "300").action(async (agentInput, opts) => {
4041
+ program2.command("call <agent>").description("Call an agent on the A2A network (default: async polling)").requiredOption("--task <description>", "Task description").option("--input-file <path>", "Read file and append to task description").option("--output-file <path>", "Save response text to file").option("--stream", "Use SSE streaming instead of async polling").option("--json", "Output JSONL events").option("--timeout <seconds>", "Timeout in seconds", "300").action(async (agentInput, opts) => {
3866
4042
  try {
3867
4043
  const token = loadToken();
3868
4044
  if (!token) {
@@ -3883,136 +4059,22 @@ ${content}`;
3883
4059
  const timeoutMs = parseInt(opts.timeout || "300", 10) * 1e3;
3884
4060
  const abortController = new AbortController();
3885
4061
  const timer = setTimeout(() => abortController.abort(), timeoutMs);
3886
- const selfAgentId = process.env.AGENT_BRIDGE_AGENT_ID;
3887
- const res = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${id}/call`, {
3888
- method: "POST",
3889
- headers: {
3890
- Authorization: `Bearer ${token}`,
3891
- "Content-Type": "application/json",
3892
- Accept: "text/event-stream",
3893
- ...selfAgentId ? { "X-Caller-Agent-Id": selfAgentId } : {}
3894
- },
3895
- body: JSON.stringify({ task_description: taskDescription }),
4062
+ const callOpts = {
4063
+ id,
4064
+ name,
4065
+ token,
4066
+ taskDescription,
4067
+ timeoutMs,
4068
+ json: opts.json,
4069
+ outputFile: opts.outputFile,
3896
4070
  signal: abortController.signal
3897
- });
3898
- clearTimeout(timer);
3899
- if (!res.ok) {
3900
- let msg = `HTTP ${res.status}`;
3901
- let errorCode = "";
3902
- try {
3903
- const body = await res.json();
3904
- errorCode = body.error || "";
3905
- msg = body.message || body.error || msg;
3906
- } catch {
3907
- }
3908
- if (errorCode === "subscription_required") {
3909
- log.error("This is a private agent.");
3910
- console.error(` Subscribe first: agent-mesh subscribe <author-login>`);
3911
- console.error(` Then retry: agent-mesh call ${agentInput} --task "..."`);
3912
- } else {
3913
- log.error(msg);
3914
- }
3915
- process.exit(1);
3916
- }
3917
- const contentType = res.headers.get("Content-Type") || "";
3918
- if (contentType.includes("application/json")) {
3919
- const result = await res.json();
3920
- if (opts.json) {
3921
- console.log(JSON.stringify(result));
3922
- } else {
3923
- console.log("");
3924
- log.success(`Call created for ${BOLD}${name}${RESET}`);
3925
- console.log(` ${GRAY}Call ID${RESET} ${result.call_id}`);
3926
- console.log(` ${GRAY}Status${RESET} ${result.status}`);
3927
- console.log(` ${GRAY}Created${RESET} ${result.created_at}`);
3928
- console.log("");
3929
- }
3930
- return;
3931
- }
3932
- if (!res.body) {
3933
- log.error("Empty response body");
3934
- process.exit(1);
3935
- }
3936
- if (!opts.json) {
3937
- log.info(`Calling ${BOLD}${name}${RESET}...`);
3938
- console.log("");
3939
- }
3940
- const reader = res.body.getReader();
3941
- const decoder = new TextDecoder();
3942
- let buffer = "";
3943
- let outputBuffer = "";
3944
- let inThinkingBlock = false;
3945
- while (true) {
3946
- const { done, value } = await reader.read();
3947
- if (done) break;
3948
- const chunk = decoder.decode(value, { stream: true });
3949
- const parsed = parseSseChunk(chunk, buffer);
3950
- buffer = parsed.carry;
3951
- for (const data of parsed.events) {
3952
- if (data === "[DONE]") continue;
3953
- try {
3954
- const event = JSON.parse(data);
3955
- if (opts.json) {
3956
- console.log(JSON.stringify(event));
3957
- } else {
3958
- if (event.type === "chunk" && event.delta) {
3959
- process.stdout.write(event.delta);
3960
- if (!event.kind || event.kind === "text") {
3961
- const delta = event.delta;
3962
- if (delta.startsWith("{") && delta.includes('"type":')) {
3963
- if (delta.includes('"type":"thinking"') && delta.includes("content_block_start")) {
3964
- inThinkingBlock = true;
3965
- } else if (delta.includes('"type":"text"') && delta.includes("content_block_start")) {
3966
- inThinkingBlock = false;
3967
- }
3968
- } else if (!inThinkingBlock) {
3969
- outputBuffer += delta;
3970
- }
3971
- }
3972
- } else if (event.type === "done" && event.attachments?.length) {
3973
- console.log("");
3974
- for (const att of event.attachments) {
3975
- log.info(` ${GRAY}File:${RESET} ${att.name} ${GRAY}${att.url}${RESET}`);
3976
- }
3977
- } else if (event.type === "error") {
3978
- process.stderr.write(`
3979
- Error: ${event.message}
3980
- `);
3981
- }
3982
- }
3983
- } catch {
3984
- }
3985
- }
3986
- }
3987
- if (buffer.trim()) {
3988
- const parsed = parseSseChunk("\n\n", buffer);
3989
- for (const data of parsed.events) {
3990
- if (data === "[DONE]") continue;
3991
- try {
3992
- const event = JSON.parse(data);
3993
- if (opts.json) {
3994
- console.log(JSON.stringify(event));
3995
- } else if (event.type === "chunk" && event.delta) {
3996
- process.stdout.write(event.delta);
3997
- if (!event.kind || event.kind === "text") {
3998
- const delta = event.delta;
3999
- if (!(delta.startsWith("{") && delta.includes('"type":')) && !inThinkingBlock) {
4000
- outputBuffer += delta;
4001
- }
4002
- }
4003
- }
4004
- } catch {
4005
- }
4006
- }
4007
- }
4008
- if (opts.outputFile && outputBuffer) {
4009
- writeFileSync2(opts.outputFile, outputBuffer);
4010
- if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
4011
- }
4012
- if (!opts.json) {
4013
- console.log("\n");
4014
- log.success("Call completed");
4071
+ };
4072
+ if (opts.stream) {
4073
+ await streamCall(callOpts);
4074
+ } else {
4075
+ await asyncCall(callOpts);
4015
4076
  }
4077
+ clearTimeout(timer);
4016
4078
  } catch (err) {
4017
4079
  if (err.name === "AbortError") {
4018
4080
  log.error("Call timed out");
@@ -4250,6 +4312,68 @@ function registerSubscribeCommand(program2) {
4250
4312
  });
4251
4313
  }
4252
4314
 
4315
+ // src/commands/register.ts
4316
+ var DEFAULT_BASE_URL5 = "https://agents.hot";
4317
+ var VALID_AGENT_TYPES = ["openclaw", "claude-code", "cursor", "windsurf", "custom"];
4318
+ function registerRegisterCommand(program2) {
4319
+ program2.command("register").description("Register a new agent on the platform and get an API key").requiredOption("--name <name>", "Agent name (alphanumeric + hyphens, 3-64 chars)").option("--type <type>", "Agent type", "claude-code").option("--description <text>", "Agent description").option("--capabilities <list>", "Comma-separated capabilities").option("--base-url <url>", "Platform base URL", DEFAULT_BASE_URL5).action(async (opts) => {
4320
+ if (!VALID_AGENT_TYPES.includes(opts.type)) {
4321
+ log.error(`Invalid agent type: ${opts.type}. Must be one of: ${VALID_AGENT_TYPES.join(", ")}`);
4322
+ process.exit(1);
4323
+ }
4324
+ const capabilities = opts.capabilities ? opts.capabilities.split(",").map((c) => c.trim()).filter(Boolean) : [];
4325
+ log.info(`Registering agent ${BOLD}${opts.name}${RESET}...`);
4326
+ let res;
4327
+ try {
4328
+ res = await fetch(`${opts.baseUrl}/api/auth/agent/register`, {
4329
+ method: "POST",
4330
+ headers: { "Content-Type": "application/json" },
4331
+ body: JSON.stringify({
4332
+ agent_name: opts.name,
4333
+ agent_type: opts.type,
4334
+ description: opts.description,
4335
+ capabilities
4336
+ })
4337
+ });
4338
+ } catch (err) {
4339
+ log.error(`Network error: ${err.message}`);
4340
+ process.exit(1);
4341
+ }
4342
+ if (!res.ok) {
4343
+ let msg = `HTTP ${res.status}`;
4344
+ try {
4345
+ const body = await res.json();
4346
+ msg = body.message || body.error || msg;
4347
+ } catch {
4348
+ }
4349
+ log.error(msg);
4350
+ process.exit(1);
4351
+ }
4352
+ const data = await res.json();
4353
+ if (!hasToken()) {
4354
+ saveToken(data.api_key);
4355
+ log.info("Saved API key as platform token (auto-login)");
4356
+ }
4357
+ const slug = uniqueSlug(opts.name);
4358
+ const workspaceDir = getAgentWorkspaceDir(slug);
4359
+ addAgent(slug, {
4360
+ agentId: data.agent_id,
4361
+ agentType: opts.type,
4362
+ bridgeUrl: opts.baseUrl.replace("https://", "wss://").replace("http://", "ws://") + "/ws",
4363
+ projectPath: workspaceDir,
4364
+ addedAt: (/* @__PURE__ */ new Date()).toISOString()
4365
+ });
4366
+ log.success(`Agent registered: ${BOLD}${data.agent_name}${RESET}`);
4367
+ console.log("");
4368
+ console.log(` Agent ID: ${data.agent_id}`);
4369
+ console.log(` API Key: ${data.api_key}`);
4370
+ console.log(` Type: ${data.agent_type}`);
4371
+ console.log(` Workspace: ${workspaceDir}`);
4372
+ console.log("");
4373
+ console.log(`${GRAY}Next: agent-mesh connect ${slug}${RESET}`);
4374
+ });
4375
+ }
4376
+
4253
4377
  // src/index.ts
4254
4378
  var require2 = createRequire(import.meta.url);
4255
4379
  var { version } = require2("../package.json");
@@ -4277,4 +4401,5 @@ registerCallCommand(program);
4277
4401
  registerConfigCommand(program);
4278
4402
  registerStatsCommand(program);
4279
4403
  registerSubscribeCommand(program);
4404
+ registerRegisterCommand(program);
4280
4405
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@annals/agent-mesh",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "CLI bridge connecting local AI agents to the Agents.Hot platform",
5
5
  "type": "module",
6
6
  "bin": {