@annals/agent-mesh 0.13.1 → 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.
- package/dist/index.js +388 -129
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2611,7 +2611,8 @@ var ERROR_HINTS = {
|
|
|
2611
2611
|
github_required: "GitHub account required. Visit https://agents.hot/settings to link one.",
|
|
2612
2612
|
validation_error: "Invalid input. Check your skill.json or command flags.",
|
|
2613
2613
|
permission_denied: "You don't have permission to modify this skill.",
|
|
2614
|
-
file_too_large: "Package file exceeds the 50MB limit."
|
|
2614
|
+
file_too_large: "Package file exceeds the 50MB limit.",
|
|
2615
|
+
subscription_required: "This is a private agent. Subscribe first: agent-mesh subscribe <author-login>"
|
|
2615
2616
|
};
|
|
2616
2617
|
var PlatformClient = class {
|
|
2617
2618
|
token;
|
|
@@ -2942,18 +2943,18 @@ async function asyncChat(opts) {
|
|
|
2942
2943
|
}
|
|
2943
2944
|
throw new Error(msg);
|
|
2944
2945
|
}
|
|
2945
|
-
const {
|
|
2946
|
+
const { request_id, status, error_message, error_code } = await res.json();
|
|
2946
2947
|
if (status === "failed") {
|
|
2947
2948
|
throw new Error(`Task failed: ${error_message || error_code}`);
|
|
2948
2949
|
}
|
|
2949
|
-
process.stderr.write(`${GRAY}[async]
|
|
2950
|
+
process.stderr.write(`${GRAY}[async] request=${request_id.slice(0, 8)}... polling${RESET}`);
|
|
2950
2951
|
const maxWait = 5 * 60 * 1e3;
|
|
2951
2952
|
const pollInterval = 2e3;
|
|
2952
2953
|
const startTime = Date.now();
|
|
2953
2954
|
while (Date.now() - startTime < maxWait) {
|
|
2954
2955
|
if (opts.signal?.aborted) throw new Error("Aborted");
|
|
2955
2956
|
await sleep4(pollInterval);
|
|
2956
|
-
const pollRes = await fetch(`${opts.baseUrl}/api/
|
|
2957
|
+
const pollRes = await fetch(`${opts.baseUrl}/api/agents/${opts.agentId}/task-status/${request_id}`, {
|
|
2957
2958
|
headers: { Authorization: `Bearer ${opts.token}` },
|
|
2958
2959
|
signal: opts.signal
|
|
2959
2960
|
});
|
|
@@ -2979,7 +2980,7 @@ async function asyncChat(opts) {
|
|
|
2979
2980
|
throw new Error("Task timed out waiting for result");
|
|
2980
2981
|
}
|
|
2981
2982
|
async function streamChat(opts) {
|
|
2982
|
-
if (
|
|
2983
|
+
if (opts.mode === "async") {
|
|
2983
2984
|
return asyncChat(opts);
|
|
2984
2985
|
}
|
|
2985
2986
|
const res = await fetch(`${opts.baseUrl}/api/agents/${opts.agentId}/chat`, {
|
|
@@ -3082,7 +3083,7 @@ ${"\x1B[31m"}Error: ${event.errorText}${RESET}
|
|
|
3082
3083
|
}
|
|
3083
3084
|
}
|
|
3084
3085
|
function registerChatCommand(program2) {
|
|
3085
|
-
program2.command("chat <agent> [message]").description("Chat with an agent through the platform (for debugging)").option("--no-thinking", "Hide thinking/reasoning output").option("--
|
|
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) => {
|
|
3086
3087
|
const token = loadToken();
|
|
3087
3088
|
if (!token) {
|
|
3088
3089
|
log.error("Not authenticated. Run `agent-mesh login` first.");
|
|
@@ -3099,7 +3100,7 @@ function registerChatCommand(program2) {
|
|
|
3099
3100
|
log.error(err.message);
|
|
3100
3101
|
process.exit(1);
|
|
3101
3102
|
}
|
|
3102
|
-
const mode = opts.
|
|
3103
|
+
const mode = opts.async ? "async" : "stream";
|
|
3103
3104
|
if (inlineMessage) {
|
|
3104
3105
|
log.info(`Chatting with ${BOLD}${agentName}${RESET} (${mode})`);
|
|
3105
3106
|
try {
|
|
@@ -3807,7 +3808,10 @@ function registerDiscoverCommand(program2) {
|
|
|
3807
3808
|
params.set("limit", opts.limit);
|
|
3808
3809
|
params.set("offset", opts.offset);
|
|
3809
3810
|
const url = `${BASE_URL}/api/agents/discover?${params}`;
|
|
3810
|
-
const
|
|
3811
|
+
const token = loadToken();
|
|
3812
|
+
const headers = {};
|
|
3813
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
3814
|
+
const res = await fetch(url, { headers });
|
|
3811
3815
|
if (!res.ok) {
|
|
3812
3816
|
const body = await res.json().catch(() => ({}));
|
|
3813
3817
|
console.error(` Error: ${body.message ?? `HTTP ${res.status}`}`);
|
|
@@ -3849,6 +3853,9 @@ function registerDiscoverCommand(program2) {
|
|
|
3849
3853
|
// src/commands/call.ts
|
|
3850
3854
|
import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
3851
3855
|
var DEFAULT_BASE_URL4 = "https://agents.hot";
|
|
3856
|
+
function sleep5(ms) {
|
|
3857
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3858
|
+
}
|
|
3852
3859
|
function handleError2(err) {
|
|
3853
3860
|
if (err instanceof PlatformApiError) {
|
|
3854
3861
|
log.error(err.message);
|
|
@@ -3857,8 +3864,228 @@ function handleError2(err) {
|
|
|
3857
3864
|
}
|
|
3858
3865
|
process.exit(1);
|
|
3859
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
|
+
}
|
|
3860
4087
|
function registerCallCommand(program2) {
|
|
3861
|
-
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) => {
|
|
3862
4089
|
try {
|
|
3863
4090
|
const token = loadToken();
|
|
3864
4091
|
if (!token) {
|
|
@@ -3879,128 +4106,22 @@ ${content}`;
|
|
|
3879
4106
|
const timeoutMs = parseInt(opts.timeout || "300", 10) * 1e3;
|
|
3880
4107
|
const abortController = new AbortController();
|
|
3881
4108
|
const timer = setTimeout(() => abortController.abort(), timeoutMs);
|
|
3882
|
-
const
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
},
|
|
3891
|
-
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,
|
|
3892
4117
|
signal: abortController.signal
|
|
3893
|
-
}
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
const body = await res.json();
|
|
3899
|
-
msg = body.message || body.error || msg;
|
|
3900
|
-
} catch {
|
|
3901
|
-
}
|
|
3902
|
-
log.error(msg);
|
|
3903
|
-
process.exit(1);
|
|
3904
|
-
}
|
|
3905
|
-
const contentType = res.headers.get("Content-Type") || "";
|
|
3906
|
-
if (contentType.includes("application/json")) {
|
|
3907
|
-
const result = await res.json();
|
|
3908
|
-
if (opts.json) {
|
|
3909
|
-
console.log(JSON.stringify(result));
|
|
3910
|
-
} else {
|
|
3911
|
-
console.log("");
|
|
3912
|
-
log.success(`Call created for ${BOLD}${name}${RESET}`);
|
|
3913
|
-
console.log(` ${GRAY}Call ID${RESET} ${result.call_id}`);
|
|
3914
|
-
console.log(` ${GRAY}Status${RESET} ${result.status}`);
|
|
3915
|
-
console.log(` ${GRAY}Created${RESET} ${result.created_at}`);
|
|
3916
|
-
console.log("");
|
|
3917
|
-
}
|
|
3918
|
-
return;
|
|
3919
|
-
}
|
|
3920
|
-
if (!res.body) {
|
|
3921
|
-
log.error("Empty response body");
|
|
3922
|
-
process.exit(1);
|
|
3923
|
-
}
|
|
3924
|
-
if (!opts.json) {
|
|
3925
|
-
log.info(`Calling ${BOLD}${name}${RESET}...`);
|
|
3926
|
-
console.log("");
|
|
3927
|
-
}
|
|
3928
|
-
const reader = res.body.getReader();
|
|
3929
|
-
const decoder = new TextDecoder();
|
|
3930
|
-
let buffer = "";
|
|
3931
|
-
let outputBuffer = "";
|
|
3932
|
-
let inThinkingBlock = false;
|
|
3933
|
-
while (true) {
|
|
3934
|
-
const { done, value } = await reader.read();
|
|
3935
|
-
if (done) break;
|
|
3936
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
3937
|
-
const parsed = parseSseChunk(chunk, buffer);
|
|
3938
|
-
buffer = parsed.carry;
|
|
3939
|
-
for (const data of parsed.events) {
|
|
3940
|
-
if (data === "[DONE]") continue;
|
|
3941
|
-
try {
|
|
3942
|
-
const event = JSON.parse(data);
|
|
3943
|
-
if (opts.json) {
|
|
3944
|
-
console.log(JSON.stringify(event));
|
|
3945
|
-
} else {
|
|
3946
|
-
if (event.type === "chunk" && event.delta) {
|
|
3947
|
-
process.stdout.write(event.delta);
|
|
3948
|
-
if (!event.kind || event.kind === "text") {
|
|
3949
|
-
const delta = event.delta;
|
|
3950
|
-
if (delta.startsWith("{") && delta.includes('"type":')) {
|
|
3951
|
-
if (delta.includes('"type":"thinking"') && delta.includes("content_block_start")) {
|
|
3952
|
-
inThinkingBlock = true;
|
|
3953
|
-
} else if (delta.includes('"type":"text"') && delta.includes("content_block_start")) {
|
|
3954
|
-
inThinkingBlock = false;
|
|
3955
|
-
}
|
|
3956
|
-
} else if (!inThinkingBlock) {
|
|
3957
|
-
outputBuffer += delta;
|
|
3958
|
-
}
|
|
3959
|
-
}
|
|
3960
|
-
} else if (event.type === "done" && event.attachments?.length) {
|
|
3961
|
-
console.log("");
|
|
3962
|
-
for (const att of event.attachments) {
|
|
3963
|
-
log.info(` ${GRAY}File:${RESET} ${att.name} ${GRAY}${att.url}${RESET}`);
|
|
3964
|
-
}
|
|
3965
|
-
} else if (event.type === "error") {
|
|
3966
|
-
process.stderr.write(`
|
|
3967
|
-
Error: ${event.message}
|
|
3968
|
-
`);
|
|
3969
|
-
}
|
|
3970
|
-
}
|
|
3971
|
-
} catch {
|
|
3972
|
-
}
|
|
3973
|
-
}
|
|
3974
|
-
}
|
|
3975
|
-
if (buffer.trim()) {
|
|
3976
|
-
const parsed = parseSseChunk("\n\n", buffer);
|
|
3977
|
-
for (const data of parsed.events) {
|
|
3978
|
-
if (data === "[DONE]") continue;
|
|
3979
|
-
try {
|
|
3980
|
-
const event = JSON.parse(data);
|
|
3981
|
-
if (opts.json) {
|
|
3982
|
-
console.log(JSON.stringify(event));
|
|
3983
|
-
} else if (event.type === "chunk" && event.delta) {
|
|
3984
|
-
process.stdout.write(event.delta);
|
|
3985
|
-
if (!event.kind || event.kind === "text") {
|
|
3986
|
-
const delta = event.delta;
|
|
3987
|
-
if (!(delta.startsWith("{") && delta.includes('"type":')) && !inThinkingBlock) {
|
|
3988
|
-
outputBuffer += delta;
|
|
3989
|
-
}
|
|
3990
|
-
}
|
|
3991
|
-
}
|
|
3992
|
-
} catch {
|
|
3993
|
-
}
|
|
3994
|
-
}
|
|
3995
|
-
}
|
|
3996
|
-
if (opts.outputFile && outputBuffer) {
|
|
3997
|
-
writeFileSync2(opts.outputFile, outputBuffer);
|
|
3998
|
-
if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
|
|
3999
|
-
}
|
|
4000
|
-
if (!opts.json) {
|
|
4001
|
-
console.log("\n");
|
|
4002
|
-
log.success("Call completed");
|
|
4118
|
+
};
|
|
4119
|
+
if (opts.stream) {
|
|
4120
|
+
await streamCall(callOpts);
|
|
4121
|
+
} else {
|
|
4122
|
+
await asyncCall(callOpts);
|
|
4003
4123
|
}
|
|
4124
|
+
clearTimeout(timer);
|
|
4004
4125
|
} catch (err) {
|
|
4005
4126
|
if (err.name === "AbortError") {
|
|
4006
4127
|
log.error("Call timed out");
|
|
@@ -4164,6 +4285,142 @@ function printAgentStats(name, stats) {
|
|
|
4164
4285
|
console.log("");
|
|
4165
4286
|
}
|
|
4166
4287
|
|
|
4288
|
+
// src/commands/subscribe.ts
|
|
4289
|
+
var BASE_URL2 = "https://agents.hot";
|
|
4290
|
+
function handleError5(err) {
|
|
4291
|
+
if (err instanceof PlatformApiError) {
|
|
4292
|
+
log.error(err.message);
|
|
4293
|
+
} else {
|
|
4294
|
+
log.error(err.message);
|
|
4295
|
+
}
|
|
4296
|
+
process.exit(1);
|
|
4297
|
+
}
|
|
4298
|
+
async function resolveAuthorLogin(login) {
|
|
4299
|
+
const res = await fetch(`${BASE_URL2}/api/authors/resolve?login=${encodeURIComponent(login)}`);
|
|
4300
|
+
if (!res.ok) {
|
|
4301
|
+
if (res.status === 404) {
|
|
4302
|
+
throw new PlatformApiError(404, "not_found", `Author not found: ${login}`);
|
|
4303
|
+
}
|
|
4304
|
+
throw new PlatformApiError(res.status, "unknown", `Failed to resolve author: HTTP ${res.status}`);
|
|
4305
|
+
}
|
|
4306
|
+
return res.json();
|
|
4307
|
+
}
|
|
4308
|
+
function registerSubscribeCommand(program2) {
|
|
4309
|
+
program2.command("subscribe <author-login>").description("Subscribe to an author to access their private agents").action(async (authorLogin) => {
|
|
4310
|
+
try {
|
|
4311
|
+
const client = createClient();
|
|
4312
|
+
const author = await resolveAuthorLogin(authorLogin);
|
|
4313
|
+
await client.post(`/api/authors/${author.id}/subscribe`);
|
|
4314
|
+
log.success(`Subscribed to ${author.github_login}${author.name ? ` (${author.name})` : ""}`);
|
|
4315
|
+
} catch (err) {
|
|
4316
|
+
handleError5(err);
|
|
4317
|
+
}
|
|
4318
|
+
});
|
|
4319
|
+
program2.command("unsubscribe <author-login>").description("Unsubscribe from an author").action(async (authorLogin) => {
|
|
4320
|
+
try {
|
|
4321
|
+
const client = createClient();
|
|
4322
|
+
const author = await resolveAuthorLogin(authorLogin);
|
|
4323
|
+
await client.del(`/api/authors/${author.id}/subscribe`);
|
|
4324
|
+
log.success(`Unsubscribed from ${author.github_login}`);
|
|
4325
|
+
} catch (err) {
|
|
4326
|
+
handleError5(err);
|
|
4327
|
+
}
|
|
4328
|
+
});
|
|
4329
|
+
program2.command("subscriptions").description("List your author subscriptions").option("--json", "Output raw JSON").action(async (opts) => {
|
|
4330
|
+
try {
|
|
4331
|
+
const client = createClient();
|
|
4332
|
+
const data = await client.get("/api/user/subscriptions");
|
|
4333
|
+
if (opts.json) {
|
|
4334
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4335
|
+
return;
|
|
4336
|
+
}
|
|
4337
|
+
if (data.subscriptions.length === 0) {
|
|
4338
|
+
console.log(" No subscriptions yet.");
|
|
4339
|
+
return;
|
|
4340
|
+
}
|
|
4341
|
+
const table = renderTable(
|
|
4342
|
+
[
|
|
4343
|
+
{ key: "login", label: "AUTHOR", width: 24 },
|
|
4344
|
+
{ key: "name", label: "NAME", width: 24 },
|
|
4345
|
+
{ key: "since", label: "SINCE", width: 20 }
|
|
4346
|
+
],
|
|
4347
|
+
data.subscriptions.map((s) => ({
|
|
4348
|
+
login: s.author.github_login,
|
|
4349
|
+
name: s.author.name || `${GRAY}\u2014${RESET}`,
|
|
4350
|
+
since: new Date(s.created_at).toLocaleDateString()
|
|
4351
|
+
}))
|
|
4352
|
+
);
|
|
4353
|
+
console.log(table);
|
|
4354
|
+
console.log(`
|
|
4355
|
+
${GRAY}${data.subscriptions.length} subscription(s)${RESET}`);
|
|
4356
|
+
} catch (err) {
|
|
4357
|
+
handleError5(err);
|
|
4358
|
+
}
|
|
4359
|
+
});
|
|
4360
|
+
}
|
|
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
|
+
|
|
4167
4424
|
// src/index.ts
|
|
4168
4425
|
var require2 = createRequire(import.meta.url);
|
|
4169
4426
|
var { version } = require2("../package.json");
|
|
@@ -4190,4 +4447,6 @@ registerDiscoverCommand(program);
|
|
|
4190
4447
|
registerCallCommand(program);
|
|
4191
4448
|
registerConfigCommand(program);
|
|
4192
4449
|
registerStatsCommand(program);
|
|
4450
|
+
registerSubscribeCommand(program);
|
|
4451
|
+
registerRegisterCommand(program);
|
|
4193
4452
|
program.parse();
|