@annals/agent-mesh 0.14.0 → 0.15.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 +307 -135
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2943,18 +2943,18 @@ async function asyncChat(opts) {
2943
2943
  }
2944
2944
  throw new Error(msg);
2945
2945
  }
2946
- const { task_id, status, error_message, error_code } = await res.json();
2946
+ const { request_id, status, error_message, error_code } = await res.json();
2947
2947
  if (status === "failed") {
2948
2948
  throw new Error(`Task failed: ${error_message || error_code}`);
2949
2949
  }
2950
- process.stderr.write(`${GRAY}[async] task=${task_id.slice(0, 8)}... polling${RESET}`);
2950
+ process.stderr.write(`${GRAY}[async] request=${request_id.slice(0, 8)}... polling${RESET}`);
2951
2951
  const maxWait = 5 * 60 * 1e3;
2952
2952
  const pollInterval = 2e3;
2953
2953
  const startTime = Date.now();
2954
2954
  while (Date.now() - startTime < maxWait) {
2955
2955
  if (opts.signal?.aborted) throw new Error("Aborted");
2956
2956
  await sleep4(pollInterval);
2957
- const pollRes = await fetch(`${opts.baseUrl}/api/tasks/${task_id}`, {
2957
+ const pollRes = await fetch(`${opts.baseUrl}/api/agents/${opts.agentId}/task-status/${request_id}`, {
2958
2958
  headers: { Authorization: `Bearer ${opts.token}` },
2959
2959
  signal: opts.signal
2960
2960
  });
@@ -2980,7 +2980,7 @@ async function asyncChat(opts) {
2980
2980
  throw new Error("Task timed out waiting for result");
2981
2981
  }
2982
2982
  async function streamChat(opts) {
2983
- if ((opts.mode ?? "async") === "async") {
2983
+ if (opts.mode === "async") {
2984
2984
  return asyncChat(opts);
2985
2985
  }
2986
2986
  const res = await fetch(`${opts.baseUrl}/api/agents/${opts.agentId}/chat`, {
@@ -3083,7 +3083,7 @@ ${"\x1B[31m"}Error: ${event.errorText}${RESET}
3083
3083
  }
3084
3084
  }
3085
3085
  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) => {
3086
+ 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
3087
  const token = loadToken();
3088
3088
  if (!token) {
3089
3089
  log.error("Not authenticated. Run `agent-mesh login` first.");
@@ -3100,7 +3100,7 @@ function registerChatCommand(program2) {
3100
3100
  log.error(err.message);
3101
3101
  process.exit(1);
3102
3102
  }
3103
- const mode = opts.stream ? "stream" : "async";
3103
+ const mode = opts.async ? "async" : "stream";
3104
3104
  if (inlineMessage) {
3105
3105
  log.info(`Chatting with ${BOLD}${agentName}${RESET} (${mode})`);
3106
3106
  try {
@@ -3853,6 +3853,9 @@ function registerDiscoverCommand(program2) {
3853
3853
  // src/commands/call.ts
3854
3854
  import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
3855
3855
  var DEFAULT_BASE_URL4 = "https://agents.hot";
3856
+ function sleep5(ms) {
3857
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
3858
+ }
3856
3859
  function handleError2(err) {
3857
3860
  if (err instanceof PlatformApiError) {
3858
3861
  log.error(err.message);
@@ -3861,8 +3864,228 @@ function handleError2(err) {
3861
3864
  }
3862
3865
  process.exit(1);
3863
3866
  }
3867
+ async function asyncCall(opts) {
3868
+ const selfAgentId = process.env.AGENT_BRIDGE_AGENT_ID;
3869
+ const res = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/call`, {
3870
+ method: "POST",
3871
+ headers: {
3872
+ Authorization: `Bearer ${opts.token}`,
3873
+ "Content-Type": "application/json",
3874
+ ...selfAgentId ? { "X-Caller-Agent-Id": selfAgentId } : {}
3875
+ },
3876
+ body: JSON.stringify({ task_description: opts.taskDescription, mode: "async" }),
3877
+ signal: opts.signal
3878
+ });
3879
+ if (!res.ok) {
3880
+ let msg = `HTTP ${res.status}`;
3881
+ let errorCode = "";
3882
+ try {
3883
+ const body = await res.json();
3884
+ errorCode = body.error || "";
3885
+ msg = body.message || body.error || msg;
3886
+ } catch {
3887
+ }
3888
+ if (errorCode === "subscription_required") {
3889
+ log.error("This is a private agent.");
3890
+ console.error(` Subscribe first: agent-mesh subscribe <author-login>`);
3891
+ } else {
3892
+ log.error(msg);
3893
+ }
3894
+ process.exit(1);
3895
+ }
3896
+ const { request_id, call_id, status, error_message, error_code } = await res.json();
3897
+ if (status === "failed") {
3898
+ log.error(`Call failed: ${error_message || error_code}`);
3899
+ process.exit(1);
3900
+ }
3901
+ if (!opts.json) {
3902
+ process.stderr.write(`${GRAY}[async] call=${call_id.slice(0, 8)}... request=${request_id.slice(0, 8)}... polling${RESET}`);
3903
+ }
3904
+ const pollInterval = 2e3;
3905
+ const startTime = Date.now();
3906
+ while (Date.now() - startTime < opts.timeoutMs) {
3907
+ if (opts.signal?.aborted) {
3908
+ log.error("Aborted");
3909
+ process.exit(1);
3910
+ }
3911
+ await sleep5(pollInterval);
3912
+ const pollRes = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/task-status/${request_id}`, {
3913
+ headers: { Authorization: `Bearer ${opts.token}` },
3914
+ signal: opts.signal
3915
+ });
3916
+ if (!pollRes.ok) {
3917
+ log.error(`Poll failed: HTTP ${pollRes.status}`);
3918
+ process.exit(1);
3919
+ }
3920
+ const task = await pollRes.json();
3921
+ if (task.status === "completed") {
3922
+ if (!opts.json) {
3923
+ process.stderr.write(` done
3924
+ `);
3925
+ }
3926
+ const result = task.result || "";
3927
+ if (opts.json) {
3928
+ console.log(JSON.stringify({ call_id, request_id, status: "completed", result }));
3929
+ } else {
3930
+ process.stdout.write(result + "\n");
3931
+ }
3932
+ if (opts.outputFile && result) {
3933
+ writeFileSync2(opts.outputFile, result);
3934
+ if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
3935
+ }
3936
+ return;
3937
+ }
3938
+ if (task.status === "failed") {
3939
+ if (!opts.json) {
3940
+ process.stderr.write(` failed
3941
+ `);
3942
+ }
3943
+ log.error(`Call failed: ${task.error_message || task.error_code}`);
3944
+ process.exit(1);
3945
+ }
3946
+ if (!opts.json) {
3947
+ process.stderr.write(".");
3948
+ }
3949
+ }
3950
+ if (!opts.json) {
3951
+ process.stderr.write(` timeout
3952
+ `);
3953
+ }
3954
+ log.error("Call timed out waiting for result");
3955
+ process.exit(1);
3956
+ }
3957
+ async function streamCall(opts) {
3958
+ const selfAgentId = process.env.AGENT_BRIDGE_AGENT_ID;
3959
+ const res = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/call`, {
3960
+ method: "POST",
3961
+ headers: {
3962
+ Authorization: `Bearer ${opts.token}`,
3963
+ "Content-Type": "application/json",
3964
+ Accept: "text/event-stream",
3965
+ ...selfAgentId ? { "X-Caller-Agent-Id": selfAgentId } : {}
3966
+ },
3967
+ body: JSON.stringify({ task_description: opts.taskDescription }),
3968
+ signal: opts.signal
3969
+ });
3970
+ if (!res.ok) {
3971
+ let msg = `HTTP ${res.status}`;
3972
+ let errorCode = "";
3973
+ try {
3974
+ const body = await res.json();
3975
+ errorCode = body.error || "";
3976
+ msg = body.message || body.error || msg;
3977
+ } catch {
3978
+ }
3979
+ if (errorCode === "subscription_required") {
3980
+ log.error("This is a private agent.");
3981
+ console.error(` Subscribe first: agent-mesh subscribe <author-login>`);
3982
+ } else {
3983
+ log.error(msg);
3984
+ }
3985
+ process.exit(1);
3986
+ }
3987
+ const contentType = res.headers.get("Content-Type") || "";
3988
+ if (contentType.includes("application/json")) {
3989
+ const result = await res.json();
3990
+ if (opts.json) {
3991
+ console.log(JSON.stringify(result));
3992
+ } else {
3993
+ console.log("");
3994
+ log.success(`Call created for ${BOLD}${opts.name}${RESET}`);
3995
+ console.log(` ${GRAY}Call ID${RESET} ${result.call_id}`);
3996
+ console.log(` ${GRAY}Status${RESET} ${result.status}`);
3997
+ console.log(` ${GRAY}Created${RESET} ${result.created_at}`);
3998
+ console.log("");
3999
+ }
4000
+ return;
4001
+ }
4002
+ if (!res.body) {
4003
+ log.error("Empty response body");
4004
+ process.exit(1);
4005
+ }
4006
+ if (!opts.json) {
4007
+ log.info(`Calling ${BOLD}${opts.name}${RESET}...`);
4008
+ console.log("");
4009
+ }
4010
+ const reader = res.body.getReader();
4011
+ const decoder = new TextDecoder();
4012
+ let buffer = "";
4013
+ let outputBuffer = "";
4014
+ let inThinkingBlock = false;
4015
+ while (true) {
4016
+ const { done, value } = await reader.read();
4017
+ if (done) break;
4018
+ const chunk = decoder.decode(value, { stream: true });
4019
+ const parsed = parseSseChunk(chunk, buffer);
4020
+ buffer = parsed.carry;
4021
+ for (const data of parsed.events) {
4022
+ if (data === "[DONE]") continue;
4023
+ try {
4024
+ const event = JSON.parse(data);
4025
+ if (opts.json) {
4026
+ console.log(JSON.stringify(event));
4027
+ } else {
4028
+ if (event.type === "chunk" && event.delta) {
4029
+ process.stdout.write(event.delta);
4030
+ if (!event.kind || event.kind === "text") {
4031
+ const delta = event.delta;
4032
+ if (delta.startsWith("{") && delta.includes('"type":')) {
4033
+ if (delta.includes('"type":"thinking"') && delta.includes("content_block_start")) {
4034
+ inThinkingBlock = true;
4035
+ } else if (delta.includes('"type":"text"') && delta.includes("content_block_start")) {
4036
+ inThinkingBlock = false;
4037
+ }
4038
+ } else if (!inThinkingBlock) {
4039
+ outputBuffer += delta;
4040
+ }
4041
+ }
4042
+ } else if (event.type === "done" && event.attachments?.length) {
4043
+ console.log("");
4044
+ for (const att of event.attachments) {
4045
+ log.info(` ${GRAY}File:${RESET} ${att.name} ${GRAY}${att.url}${RESET}`);
4046
+ }
4047
+ } else if (event.type === "error") {
4048
+ process.stderr.write(`
4049
+ Error: ${event.message}
4050
+ `);
4051
+ }
4052
+ }
4053
+ } catch {
4054
+ }
4055
+ }
4056
+ }
4057
+ if (buffer.trim()) {
4058
+ const parsed = parseSseChunk("\n\n", buffer);
4059
+ for (const data of parsed.events) {
4060
+ if (data === "[DONE]") continue;
4061
+ try {
4062
+ const event = JSON.parse(data);
4063
+ if (opts.json) {
4064
+ console.log(JSON.stringify(event));
4065
+ } else if (event.type === "chunk" && event.delta) {
4066
+ process.stdout.write(event.delta);
4067
+ if (!event.kind || event.kind === "text") {
4068
+ const delta = event.delta;
4069
+ if (!(delta.startsWith("{") && delta.includes('"type":')) && !inThinkingBlock) {
4070
+ outputBuffer += delta;
4071
+ }
4072
+ }
4073
+ }
4074
+ } catch {
4075
+ }
4076
+ }
4077
+ }
4078
+ if (opts.outputFile && outputBuffer) {
4079
+ writeFileSync2(opts.outputFile, outputBuffer);
4080
+ if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
4081
+ }
4082
+ if (!opts.json) {
4083
+ console.log("\n");
4084
+ log.success("Call completed");
4085
+ }
4086
+ }
3864
4087
  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) => {
4088
+ 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
4089
  try {
3867
4090
  const token = loadToken();
3868
4091
  if (!token) {
@@ -3883,136 +4106,22 @@ ${content}`;
3883
4106
  const timeoutMs = parseInt(opts.timeout || "300", 10) * 1e3;
3884
4107
  const abortController = new AbortController();
3885
4108
  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 }),
4109
+ const callOpts = {
4110
+ id,
4111
+ name,
4112
+ token,
4113
+ taskDescription,
4114
+ timeoutMs,
4115
+ json: opts.json,
4116
+ outputFile: opts.outputFile,
3896
4117
  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");
4118
+ };
4119
+ if (opts.stream) {
4120
+ await streamCall(callOpts);
4121
+ } else {
4122
+ await asyncCall(callOpts);
4015
4123
  }
4124
+ clearTimeout(timer);
4016
4125
  } catch (err) {
4017
4126
  if (err.name === "AbortError") {
4018
4127
  log.error("Call timed out");
@@ -4250,6 +4359,68 @@ function registerSubscribeCommand(program2) {
4250
4359
  });
4251
4360
  }
4252
4361
 
4362
+ // src/commands/register.ts
4363
+ var DEFAULT_BASE_URL5 = "https://agents.hot";
4364
+ var VALID_AGENT_TYPES = ["openclaw", "claude-code", "cursor", "windsurf", "custom"];
4365
+ function registerRegisterCommand(program2) {
4366
+ 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) => {
4367
+ if (!VALID_AGENT_TYPES.includes(opts.type)) {
4368
+ log.error(`Invalid agent type: ${opts.type}. Must be one of: ${VALID_AGENT_TYPES.join(", ")}`);
4369
+ process.exit(1);
4370
+ }
4371
+ const capabilities = opts.capabilities ? opts.capabilities.split(",").map((c) => c.trim()).filter(Boolean) : [];
4372
+ log.info(`Registering agent ${BOLD}${opts.name}${RESET}...`);
4373
+ let res;
4374
+ try {
4375
+ res = await fetch(`${opts.baseUrl}/api/auth/agent/register`, {
4376
+ method: "POST",
4377
+ headers: { "Content-Type": "application/json" },
4378
+ body: JSON.stringify({
4379
+ agent_name: opts.name,
4380
+ agent_type: opts.type,
4381
+ description: opts.description,
4382
+ capabilities
4383
+ })
4384
+ });
4385
+ } catch (err) {
4386
+ log.error(`Network error: ${err.message}`);
4387
+ process.exit(1);
4388
+ }
4389
+ if (!res.ok) {
4390
+ let msg = `HTTP ${res.status}`;
4391
+ try {
4392
+ const body = await res.json();
4393
+ msg = body.message || body.error || msg;
4394
+ } catch {
4395
+ }
4396
+ log.error(msg);
4397
+ process.exit(1);
4398
+ }
4399
+ const data = await res.json();
4400
+ if (!hasToken()) {
4401
+ saveToken(data.api_key);
4402
+ log.info("Saved API key as platform token (auto-login)");
4403
+ }
4404
+ const slug = uniqueSlug(opts.name);
4405
+ const workspaceDir = getAgentWorkspaceDir(slug);
4406
+ addAgent(slug, {
4407
+ agentId: data.agent_id,
4408
+ agentType: opts.type,
4409
+ bridgeUrl: opts.baseUrl.replace("https://", "wss://").replace("http://", "ws://") + "/ws",
4410
+ projectPath: workspaceDir,
4411
+ addedAt: (/* @__PURE__ */ new Date()).toISOString()
4412
+ });
4413
+ log.success(`Agent registered: ${BOLD}${data.agent_name}${RESET}`);
4414
+ console.log("");
4415
+ console.log(` Agent ID: ${data.agent_id}`);
4416
+ console.log(` API Key: ${data.api_key}`);
4417
+ console.log(` Type: ${data.agent_type}`);
4418
+ console.log(` Workspace: ${workspaceDir}`);
4419
+ console.log("");
4420
+ console.log(`${GRAY}Next: agent-mesh connect ${slug}${RESET}`);
4421
+ });
4422
+ }
4423
+
4253
4424
  // src/index.ts
4254
4425
  var require2 = createRequire(import.meta.url);
4255
4426
  var { version } = require2("../package.json");
@@ -4277,4 +4448,5 @@ registerCallCommand(program);
4277
4448
  registerConfigCommand(program);
4278
4449
  registerStatsCommand(program);
4279
4450
  registerSubscribeCommand(program);
4451
+ registerRegisterCommand(program);
4280
4452
  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.0",
4
4
  "description": "CLI bridge connecting local AI agents to the Agents.Hot platform",
5
5
  "type": "module",
6
6
  "bin": {