@neiracore/mcp-server 1.3.0 → 2.0.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.
- package/dist/index.js +474 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -814,6 +814,473 @@ ${lines.join("\n")}`
|
|
|
814
814
|
}
|
|
815
815
|
);
|
|
816
816
|
}
|
|
817
|
+
var InputSchema9 = {
|
|
818
|
+
title: zod.z.string().min(1, "Task title is required").max(256, "Title must be 256 characters or less"),
|
|
819
|
+
description: zod.z.string().min(1, "Task description is required").max(4096, "Description must be 4096 characters or less"),
|
|
820
|
+
requirements: zod.z.array(zod.z.string()).optional().describe("Required capabilities: ['frontend', 'react', 'design']"),
|
|
821
|
+
priority: zod.z.enum(["low", "normal", "high", "urgent"]).optional().default("normal"),
|
|
822
|
+
deadline: zod.z.string().optional().describe("Optional ISO 8601 deadline"),
|
|
823
|
+
target_aid: zod.z.string().regex(/^[0-9a-f]{50}$/i, "AID must be 50 hex characters").optional().describe("Optional: assign directly to a specific agent AID")
|
|
824
|
+
};
|
|
825
|
+
function registerCreateTaskTool(server, ctx) {
|
|
826
|
+
server.tool(
|
|
827
|
+
"neiracore_create_task",
|
|
828
|
+
"Create a new task on the Neiracore network. Other agents can claim it. Use for delegating work.",
|
|
829
|
+
InputSchema9,
|
|
830
|
+
async (args) => {
|
|
831
|
+
try {
|
|
832
|
+
ctx.requireAuth();
|
|
833
|
+
const creds = ctx.credentials;
|
|
834
|
+
ctx.log("info", `Creating task: ${args.title}`);
|
|
835
|
+
const body = {
|
|
836
|
+
aid: creds.aid,
|
|
837
|
+
title: args.title,
|
|
838
|
+
description: args.description,
|
|
839
|
+
priority: args.priority
|
|
840
|
+
};
|
|
841
|
+
if (args.requirements?.length) body.requirements = args.requirements;
|
|
842
|
+
if (args.deadline) body.deadline = args.deadline;
|
|
843
|
+
if (args.target_aid) body.target_aid = args.target_aid;
|
|
844
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks`, {
|
|
845
|
+
method: "POST",
|
|
846
|
+
headers: {
|
|
847
|
+
"Content-Type": "application/json",
|
|
848
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
849
|
+
},
|
|
850
|
+
body: JSON.stringify(body)
|
|
851
|
+
});
|
|
852
|
+
if (!res.ok) {
|
|
853
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
854
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
855
|
+
}
|
|
856
|
+
const result = await res.json();
|
|
857
|
+
const task = result.task ?? result;
|
|
858
|
+
const taskId = String(task.id ?? "(unknown)");
|
|
859
|
+
const status = String(task.status ?? "open");
|
|
860
|
+
ctx.log("info", `Task created: ${taskId}`);
|
|
861
|
+
const output = [
|
|
862
|
+
"\u{1F4CB} Task created!\n",
|
|
863
|
+
formatSection("", [
|
|
864
|
+
["Task ID", taskId],
|
|
865
|
+
["Title", String(task.title ?? args.title)],
|
|
866
|
+
["Status", status],
|
|
867
|
+
["Priority", String(task.priority ?? args.priority)],
|
|
868
|
+
["Deadline", args.deadline ?? "(none)"],
|
|
869
|
+
["Target", args.target_aid ? args.target_aid.slice(0, 12) + "\u2026" : "(open auction)"]
|
|
870
|
+
]),
|
|
871
|
+
"",
|
|
872
|
+
args.target_aid ? "Task assigned directly to the target agent." : "Task is now visible on the task board. Agents can claim it.",
|
|
873
|
+
"\nUse neiracore_task_status to monitor progress."
|
|
874
|
+
].join("\n");
|
|
875
|
+
return textResult(output);
|
|
876
|
+
} catch (err) {
|
|
877
|
+
ctx.log("error", `Create task failed: ${String(err)}`);
|
|
878
|
+
return handleToolError(err);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
var InputSchema10 = {
|
|
884
|
+
status: zod.z.enum(["open", "claimed", "in_progress", "review", "done", "failed"]).optional().default("open"),
|
|
885
|
+
priority: zod.z.enum(["low", "normal", "high", "urgent"]).optional(),
|
|
886
|
+
limit: zod.z.number().int().min(1).max(100).optional().default(10)
|
|
887
|
+
};
|
|
888
|
+
function registerListTasksTool(server, ctx) {
|
|
889
|
+
server.tool(
|
|
890
|
+
"neiracore_list_tasks",
|
|
891
|
+
"Browse available tasks on the Neiracore network. Filter by status and priority. Check periodically for new work opportunities.",
|
|
892
|
+
InputSchema10,
|
|
893
|
+
async (args) => {
|
|
894
|
+
try {
|
|
895
|
+
ctx.requireAuth();
|
|
896
|
+
const creds = ctx.credentials;
|
|
897
|
+
ctx.log("debug", `Listing tasks: status=${args.status} priority=${args.priority ?? "any"} limit=${args.limit}`);
|
|
898
|
+
const params = new URLSearchParams();
|
|
899
|
+
params.set("aid", creds.aid);
|
|
900
|
+
params.set("status", args.status);
|
|
901
|
+
params.set("limit", String(args.limit));
|
|
902
|
+
if (args.priority) params.set("priority", args.priority);
|
|
903
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks?${params.toString()}`, {
|
|
904
|
+
headers: {
|
|
905
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
if (!res.ok) {
|
|
909
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
910
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
911
|
+
}
|
|
912
|
+
const result = await res.json();
|
|
913
|
+
const tasks = result.tasks ?? [];
|
|
914
|
+
const total = result.total ?? tasks.length;
|
|
915
|
+
if (tasks.length === 0) {
|
|
916
|
+
return textResult(
|
|
917
|
+
`\u{1F4CB} No tasks found with status="${args.status}"${args.priority ? ` and priority="${args.priority}"` : ""}.
|
|
918
|
+
|
|
919
|
+
Try different filters or check back later.`
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
const priorityIcon = {
|
|
923
|
+
low: "\u2B1C",
|
|
924
|
+
normal: "\u{1F7E6}",
|
|
925
|
+
high: "\u{1F7E7}",
|
|
926
|
+
urgent: "\u{1F534}"
|
|
927
|
+
};
|
|
928
|
+
const lines = [
|
|
929
|
+
`\u{1F4CB} Tasks (${tasks.length} of ${total}, status: ${args.status})
|
|
930
|
+
`
|
|
931
|
+
];
|
|
932
|
+
for (let i = 0; i < tasks.length; i++) {
|
|
933
|
+
const t = tasks[i];
|
|
934
|
+
const icon = priorityIcon[t.priority ?? "normal"] ?? "\u{1F7E6}";
|
|
935
|
+
const reqs = t.requirements?.length ? t.requirements.join(", ") : "none";
|
|
936
|
+
const deadline = t.deadline ? new Date(t.deadline).toLocaleDateString() : "\u2014";
|
|
937
|
+
const claims = t.claims_count ?? 0;
|
|
938
|
+
lines.push(
|
|
939
|
+
`${i + 1}. ${icon} **${truncate(t.title ?? "(untitled)", 60)}**`,
|
|
940
|
+
` ID: ${t.id ?? "?"}`,
|
|
941
|
+
` Priority: ${t.priority ?? "normal"} | Claims: ${claims} | Deadline: ${deadline}`,
|
|
942
|
+
` Requirements: ${reqs}`,
|
|
943
|
+
` ${truncate(t.description ?? "", 100)}`,
|
|
944
|
+
""
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
if (result.has_more) {
|
|
948
|
+
lines.push(`Showing ${tasks.length} of ${total}. Increase limit to see more.`);
|
|
949
|
+
}
|
|
950
|
+
lines.push("\nUse neiracore_claim_task to claim a task you want to work on.");
|
|
951
|
+
return textResult(lines.join("\n"));
|
|
952
|
+
} catch (err) {
|
|
953
|
+
ctx.log("error", `List tasks failed: ${String(err)}`);
|
|
954
|
+
return handleToolError(err);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
var InputSchema11 = {
|
|
960
|
+
task_id: zod.z.string().uuid("Task ID must be a valid UUID"),
|
|
961
|
+
message: zod.z.string().max(1024, "Message must be 1024 characters or less").optional().describe("Your pitch: why you're qualified for this task")
|
|
962
|
+
};
|
|
963
|
+
function registerClaimTaskTool(server, ctx) {
|
|
964
|
+
server.tool(
|
|
965
|
+
"neiracore_claim_task",
|
|
966
|
+
"Claim an open task to work on it. Provide a short pitch explaining why you're a good fit. The task will be assigned to you immediately if max_claims=1.",
|
|
967
|
+
InputSchema11,
|
|
968
|
+
async (args) => {
|
|
969
|
+
try {
|
|
970
|
+
ctx.requireAuth();
|
|
971
|
+
const creds = ctx.credentials;
|
|
972
|
+
ctx.log("info", `Claiming task: ${args.task_id.slice(0, 8)}...`);
|
|
973
|
+
const body = {
|
|
974
|
+
aid: creds.aid,
|
|
975
|
+
task_id: args.task_id
|
|
976
|
+
};
|
|
977
|
+
if (args.message) body.message = args.message;
|
|
978
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks/claim`, {
|
|
979
|
+
method: "POST",
|
|
980
|
+
headers: {
|
|
981
|
+
"Content-Type": "application/json",
|
|
982
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
983
|
+
},
|
|
984
|
+
body: JSON.stringify(body)
|
|
985
|
+
});
|
|
986
|
+
if (!res.ok) {
|
|
987
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
988
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
989
|
+
}
|
|
990
|
+
const result = await res.json();
|
|
991
|
+
const claim = result.claim ?? {};
|
|
992
|
+
const claimStatus = claim.status ?? "pending";
|
|
993
|
+
const matchScore = claim.match_score != null ? `${Math.round(claim.match_score * 100)}%` : "\u2014";
|
|
994
|
+
const icon = claimStatus === "accepted" ? "\u2705" : "\u23F3";
|
|
995
|
+
const lines = [
|
|
996
|
+
`${icon} Task claim ${claimStatus}!
|
|
997
|
+
`,
|
|
998
|
+
` Task ID: ${args.task_id}`,
|
|
999
|
+
` Claim Status: ${claimStatus}`,
|
|
1000
|
+
` Match Score: ${matchScore}`,
|
|
1001
|
+
` Task Status: ${result.task_status ?? "\u2014"}`
|
|
1002
|
+
];
|
|
1003
|
+
if (claimStatus === "accepted") {
|
|
1004
|
+
lines.push(
|
|
1005
|
+
"",
|
|
1006
|
+
"You are now assigned to this task.",
|
|
1007
|
+
"Use neiracore_task_status with action='start' when ready to begin work."
|
|
1008
|
+
);
|
|
1009
|
+
} else {
|
|
1010
|
+
lines.push(
|
|
1011
|
+
"",
|
|
1012
|
+
"Your claim is pending. The task creator will review and decide."
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
return textResult(lines.join("\n"));
|
|
1016
|
+
} catch (err) {
|
|
1017
|
+
ctx.log("error", `Claim task failed: ${String(err)}`);
|
|
1018
|
+
return handleToolError(err);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
var InputSchema12 = {
|
|
1024
|
+
task_id: zod.z.string().uuid("Task ID must be a valid UUID"),
|
|
1025
|
+
result: zod.z.string().min(1, "Result text is required").max(4096, "Result must be 4096 characters or less").describe("Human-readable result summary"),
|
|
1026
|
+
failed: zod.z.boolean().optional().default(false).describe("Set to true if the task could not be completed")
|
|
1027
|
+
};
|
|
1028
|
+
function registerSubmitResultTool(server, ctx) {
|
|
1029
|
+
server.tool(
|
|
1030
|
+
"neiracore_submit_result",
|
|
1031
|
+
"Submit the result of a task you're working on. Include a text summary of what was accomplished. Set failed=true if you could not complete the task.",
|
|
1032
|
+
InputSchema12,
|
|
1033
|
+
async (args) => {
|
|
1034
|
+
try {
|
|
1035
|
+
ctx.requireAuth();
|
|
1036
|
+
const creds = ctx.credentials;
|
|
1037
|
+
ctx.log("info", `Submitting result for task: ${args.task_id.slice(0, 8)}... failed=${args.failed}`);
|
|
1038
|
+
const body = {
|
|
1039
|
+
aid: creds.aid,
|
|
1040
|
+
task_id: args.task_id,
|
|
1041
|
+
result_text: args.result,
|
|
1042
|
+
failed: args.failed
|
|
1043
|
+
};
|
|
1044
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks/submit`, {
|
|
1045
|
+
method: "POST",
|
|
1046
|
+
headers: {
|
|
1047
|
+
"Content-Type": "application/json",
|
|
1048
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
1049
|
+
},
|
|
1050
|
+
body: JSON.stringify(body)
|
|
1051
|
+
});
|
|
1052
|
+
if (!res.ok) {
|
|
1053
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1054
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
1055
|
+
}
|
|
1056
|
+
const result = await res.json();
|
|
1057
|
+
const newStatus = result.status ?? (args.failed ? "failed" : "review");
|
|
1058
|
+
const icon = args.failed ? "\u274C" : "\u{1F4E4}";
|
|
1059
|
+
const lines = [
|
|
1060
|
+
`${icon} Result submitted!
|
|
1061
|
+
`,
|
|
1062
|
+
` Task ID: ${args.task_id}`,
|
|
1063
|
+
` Status: ${newStatus}`,
|
|
1064
|
+
` Result: ${truncate(args.result, 100)}`
|
|
1065
|
+
];
|
|
1066
|
+
if (args.failed) {
|
|
1067
|
+
lines.push(
|
|
1068
|
+
"",
|
|
1069
|
+
"Task marked as failed. The creator will be notified."
|
|
1070
|
+
);
|
|
1071
|
+
} else {
|
|
1072
|
+
lines.push(
|
|
1073
|
+
"",
|
|
1074
|
+
"Result submitted for review. The task creator will approve or request changes."
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
return textResult(lines.join("\n"));
|
|
1078
|
+
} catch (err) {
|
|
1079
|
+
ctx.log("error", `Submit result failed: ${String(err)}`);
|
|
1080
|
+
return handleToolError(err);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
var InputSchema13 = {
|
|
1086
|
+
task_id: zod.z.string().uuid("Task ID must be a valid UUID"),
|
|
1087
|
+
action: zod.z.enum(["start", "cancel", "approve", "reject", "unclaim"]).optional().describe("Action to perform. Omit to just view task details.")
|
|
1088
|
+
};
|
|
1089
|
+
function registerTaskStatusTool(server, ctx) {
|
|
1090
|
+
server.tool(
|
|
1091
|
+
"neiracore_task_status",
|
|
1092
|
+
"Get detailed status of a task including claims, subtasks, and messages. Optionally update status: start (begin work), cancel, approve/reject (results), unclaim (withdraw).",
|
|
1093
|
+
InputSchema13,
|
|
1094
|
+
async (args) => {
|
|
1095
|
+
try {
|
|
1096
|
+
ctx.requireAuth();
|
|
1097
|
+
const creds = ctx.credentials;
|
|
1098
|
+
if (!args.action) {
|
|
1099
|
+
return await getTaskDetails(ctx, creds, args.task_id);
|
|
1100
|
+
}
|
|
1101
|
+
return await updateTaskStatus(ctx, creds, args.task_id, args.action);
|
|
1102
|
+
} catch (err) {
|
|
1103
|
+
ctx.log("error", `Task status failed: ${String(err)}`);
|
|
1104
|
+
return handleToolError(err);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
1109
|
+
async function getTaskDetails(ctx, creds, taskId) {
|
|
1110
|
+
ctx.log("debug", `Getting task details: ${taskId.slice(0, 8)}...`);
|
|
1111
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks/${taskId}?aid=${creds.aid}`, {
|
|
1112
|
+
headers: {
|
|
1113
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
if (!res.ok) {
|
|
1117
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1118
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
1119
|
+
}
|
|
1120
|
+
const result = await res.json();
|
|
1121
|
+
const task = result.task ?? {};
|
|
1122
|
+
const claims = result.claims ?? [];
|
|
1123
|
+
const subtasks = result.subtasks ?? [];
|
|
1124
|
+
const messages = result.messages ?? [];
|
|
1125
|
+
const statusIcon = {
|
|
1126
|
+
open: "\u{1F7E2}",
|
|
1127
|
+
claimed: "\u{1F7E1}",
|
|
1128
|
+
in_progress: "\u{1F535}",
|
|
1129
|
+
review: "\u{1F7E3}",
|
|
1130
|
+
done: "\u2705",
|
|
1131
|
+
failed: "\u274C",
|
|
1132
|
+
cancelled: "\u2B1B",
|
|
1133
|
+
expired: "\u23F0"
|
|
1134
|
+
};
|
|
1135
|
+
const icon = statusIcon[task.status ?? ""] ?? "\u2753";
|
|
1136
|
+
const lines = [
|
|
1137
|
+
`${icon} Task: ${task.title ?? "(untitled)"}
|
|
1138
|
+
`,
|
|
1139
|
+
formatSection("Details", [
|
|
1140
|
+
["ID", task.id],
|
|
1141
|
+
["Status", task.status],
|
|
1142
|
+
["Priority", task.priority],
|
|
1143
|
+
["Creator", task.creator_name ?? task.creator_aid?.slice(0, 12)],
|
|
1144
|
+
["Assigned", task.assigned_name ?? task.assigned_aid?.slice(0, 12) ?? "(unassigned)"],
|
|
1145
|
+
["Requirements", task.requirements?.join(", ") ?? "none"],
|
|
1146
|
+
["Deadline", task.deadline ?? "\u2014"],
|
|
1147
|
+
["Created", task.created_at],
|
|
1148
|
+
["Claimed", task.claimed_at ?? "\u2014"],
|
|
1149
|
+
["Started", task.started_at ?? "\u2014"],
|
|
1150
|
+
["Completed", task.completed_at ?? "\u2014"]
|
|
1151
|
+
])
|
|
1152
|
+
];
|
|
1153
|
+
if (task.description) {
|
|
1154
|
+
lines.push("", `Description: ${truncate(task.description, 200)}`);
|
|
1155
|
+
}
|
|
1156
|
+
if (task.result_text) {
|
|
1157
|
+
lines.push("", `Result: ${truncate(task.result_text, 200)}`);
|
|
1158
|
+
}
|
|
1159
|
+
if (claims.length > 0) {
|
|
1160
|
+
lines.push("\n\u{1F4E8} Claims:");
|
|
1161
|
+
for (const c of claims) {
|
|
1162
|
+
const name = c.agent_name ?? c.agent_aid?.slice(0, 12) ?? "?";
|
|
1163
|
+
const score = c.match_score != null ? ` (${Math.round(c.match_score * 100)}% match)` : "";
|
|
1164
|
+
lines.push(` \u2022 ${name} \u2014 ${c.status}${score}${c.message ? `: "${truncate(c.message, 60)}"` : ""}`);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (subtasks.length > 0) {
|
|
1168
|
+
lines.push("\n\u{1F4C2} Subtasks:");
|
|
1169
|
+
for (const s of subtasks) {
|
|
1170
|
+
const sIcon = statusIcon[s.status ?? ""] ?? "\u2753";
|
|
1171
|
+
lines.push(` ${sIcon} ${s.title ?? "?"} (${s.status}) \u2014 ${s.assigned_name ?? "unassigned"}`);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
if (messages.length > 0) {
|
|
1175
|
+
lines.push("\n\u{1F4AC} Recent messages:");
|
|
1176
|
+
const recent = messages.slice(-5);
|
|
1177
|
+
for (const m of recent) {
|
|
1178
|
+
const sender = m.sender_name ?? m.sender_aid?.slice(0, 10) ?? "?";
|
|
1179
|
+
const time = m.created_at?.slice(11, 19) ?? "";
|
|
1180
|
+
lines.push(` [${time}] ${sender}: ${truncate(m.content ?? "", 80)}`);
|
|
1181
|
+
}
|
|
1182
|
+
if (messages.length > 5) {
|
|
1183
|
+
lines.push(` ... and ${messages.length - 5} more`);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
return textResult(lines.join("\n"));
|
|
1187
|
+
}
|
|
1188
|
+
async function updateTaskStatus(ctx, creds, taskId, action) {
|
|
1189
|
+
ctx.log("info", `Updating task ${taskId.slice(0, 8)}... action=${action}`);
|
|
1190
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks/update`, {
|
|
1191
|
+
method: "POST",
|
|
1192
|
+
headers: {
|
|
1193
|
+
"Content-Type": "application/json",
|
|
1194
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
1195
|
+
},
|
|
1196
|
+
body: JSON.stringify({
|
|
1197
|
+
aid: creds.aid,
|
|
1198
|
+
task_id: taskId,
|
|
1199
|
+
action
|
|
1200
|
+
})
|
|
1201
|
+
});
|
|
1202
|
+
if (!res.ok) {
|
|
1203
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1204
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
1205
|
+
}
|
|
1206
|
+
const result = await res.json();
|
|
1207
|
+
const actionMessages = {
|
|
1208
|
+
start: "\u{1F680} Work started! Task is now in progress.",
|
|
1209
|
+
cancel: "\u2B1B Task cancelled.",
|
|
1210
|
+
approve: "\u2705 Result approved! Task is done.",
|
|
1211
|
+
reject: "\u{1F519} Result rejected. Task re-opened for new claims.",
|
|
1212
|
+
unclaim: "\u21A9\uFE0F Task unclaimed. It's back on the task board."
|
|
1213
|
+
};
|
|
1214
|
+
const msg = actionMessages[action] ?? `Action "${action}" completed.`;
|
|
1215
|
+
return textResult(
|
|
1216
|
+
`${msg}
|
|
1217
|
+
|
|
1218
|
+
Task ID: ${taskId}
|
|
1219
|
+
New Status: ${result.status ?? "updated"}`
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
var InputSchema14 = {
|
|
1223
|
+
parent_task_id: zod.z.string().uuid("Parent task ID must be a valid UUID"),
|
|
1224
|
+
title: zod.z.string().min(1, "Subtask title is required").max(256, "Title must be 256 characters or less"),
|
|
1225
|
+
description: zod.z.string().min(1, "Subtask description is required").max(4096, "Description must be 4096 characters or less"),
|
|
1226
|
+
requirements: zod.z.array(zod.z.string()).optional().describe("Required capabilities for this subtask"),
|
|
1227
|
+
target_aid: zod.z.string().regex(/^[0-9a-f]{50}$/i, "AID must be 50 hex characters").optional().describe("Optional: assign directly to a specific agent")
|
|
1228
|
+
};
|
|
1229
|
+
function registerDelegateTaskTool(server, ctx) {
|
|
1230
|
+
server.tool(
|
|
1231
|
+
"neiracore_delegate_task",
|
|
1232
|
+
"Create a subtask under an existing task. Use this to decompose complex tasks into smaller pieces that other agents can claim independently.",
|
|
1233
|
+
InputSchema14,
|
|
1234
|
+
async (args) => {
|
|
1235
|
+
try {
|
|
1236
|
+
ctx.requireAuth();
|
|
1237
|
+
const creds = ctx.credentials;
|
|
1238
|
+
ctx.log("info", `Delegating subtask under ${args.parent_task_id.slice(0, 8)}...: ${args.title}`);
|
|
1239
|
+
const body = {
|
|
1240
|
+
aid: creds.aid,
|
|
1241
|
+
parent_id: args.parent_task_id,
|
|
1242
|
+
title: args.title,
|
|
1243
|
+
description: args.description
|
|
1244
|
+
};
|
|
1245
|
+
if (args.requirements?.length) body.requirements = args.requirements;
|
|
1246
|
+
if (args.target_aid) body.target_aid = args.target_aid;
|
|
1247
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/tasks`, {
|
|
1248
|
+
method: "POST",
|
|
1249
|
+
headers: {
|
|
1250
|
+
"Content-Type": "application/json",
|
|
1251
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
1252
|
+
},
|
|
1253
|
+
body: JSON.stringify(body)
|
|
1254
|
+
});
|
|
1255
|
+
if (!res.ok) {
|
|
1256
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
1257
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
1258
|
+
}
|
|
1259
|
+
const result = await res.json();
|
|
1260
|
+
const subtask = result.task ?? result;
|
|
1261
|
+
const subtaskId = String(subtask.id ?? "(unknown)");
|
|
1262
|
+
ctx.log("info", `Subtask created: ${subtaskId}`);
|
|
1263
|
+
const output = [
|
|
1264
|
+
"\u{1F4C2} Subtask created!\n",
|
|
1265
|
+
formatSection("", [
|
|
1266
|
+
["Subtask ID", subtaskId],
|
|
1267
|
+
["Parent ID", args.parent_task_id],
|
|
1268
|
+
["Title", String(subtask.title ?? args.title)],
|
|
1269
|
+
["Status", String(subtask.status ?? "open")],
|
|
1270
|
+
["Target", args.target_aid ? args.target_aid.slice(0, 12) + "\u2026" : "(open auction)"]
|
|
1271
|
+
]),
|
|
1272
|
+
"",
|
|
1273
|
+
"Subtask is now on the task board. Agents can claim it independently.",
|
|
1274
|
+
"\nUse neiracore_task_status to monitor the parent task and all subtasks."
|
|
1275
|
+
].join("\n");
|
|
1276
|
+
return textResult(output);
|
|
1277
|
+
} catch (err) {
|
|
1278
|
+
ctx.log("error", `Delegate task failed: ${String(err)}`);
|
|
1279
|
+
return handleToolError(err);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
817
1284
|
|
|
818
1285
|
// src/tools/index.ts
|
|
819
1286
|
function registerAllTools(server, ctx) {
|
|
@@ -828,7 +1295,13 @@ function registerAllTools(server, ctx) {
|
|
|
828
1295
|
registerListChannelsTool(server, ctx);
|
|
829
1296
|
registerGroupMessageTool(server, ctx);
|
|
830
1297
|
registerGroupHistoryTool(server, ctx);
|
|
831
|
-
|
|
1298
|
+
registerCreateTaskTool(server, ctx);
|
|
1299
|
+
registerListTasksTool(server, ctx);
|
|
1300
|
+
registerClaimTaskTool(server, ctx);
|
|
1301
|
+
registerSubmitResultTool(server, ctx);
|
|
1302
|
+
registerTaskStatusTool(server, ctx);
|
|
1303
|
+
registerDelegateTaskTool(server, ctx);
|
|
1304
|
+
ctx.log("debug", "Registered 17 tools");
|
|
832
1305
|
}
|
|
833
1306
|
function registerAgentProfileResource(server, ctx) {
|
|
834
1307
|
server.resource(
|