@runtypelabs/a2a-aisdk-example 0.2.4 → 0.3.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/README.md +26 -18
- package/dist/{chunk-FTWT3LGM.js → chunk-EY4P4D5Y.js} +261 -149
- package/dist/chunk-EY4P4D5Y.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +114 -45
- package/dist/index.js +1 -1
- package/dist/vercel/index.d.ts +8 -7
- package/dist/vercel/index.js +165 -81
- package/dist/vercel/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FTWT3LGM.js.map +0 -1
|
@@ -7,11 +7,20 @@ var JSON_RPC_ERRORS = {
|
|
|
7
7
|
METHOD_NOT_FOUND: -32601,
|
|
8
8
|
INVALID_PARAMS: -32602,
|
|
9
9
|
INTERNAL_ERROR: -32603,
|
|
10
|
-
//
|
|
10
|
+
// A2A spec error codes
|
|
11
11
|
TASK_NOT_FOUND: -32001,
|
|
12
|
+
TASK_NOT_CANCELABLE: -32002,
|
|
13
|
+
PUSH_NOTIFICATION_NOT_SUPPORTED: -32003,
|
|
14
|
+
UNSUPPORTED_OPERATION: -32004,
|
|
15
|
+
CONTENT_TYPE_NOT_SUPPORTED: -32005,
|
|
16
|
+
INVALID_AGENT_RESPONSE: -32006,
|
|
17
|
+
/** @deprecated Use TASK_NOT_CANCELABLE */
|
|
12
18
|
SKILL_NOT_FOUND: -32002,
|
|
19
|
+
/** @deprecated */
|
|
13
20
|
UNAUTHORIZED: -32003,
|
|
21
|
+
/** @deprecated */
|
|
14
22
|
RATE_LIMITED: -32004,
|
|
23
|
+
/** @deprecated */
|
|
15
24
|
TASK_CANCELED: -32005
|
|
16
25
|
};
|
|
17
26
|
|
|
@@ -39,10 +48,10 @@ function createResponse(result, source) {
|
|
|
39
48
|
}
|
|
40
49
|
function extractInput(message) {
|
|
41
50
|
for (const part of message.parts) {
|
|
42
|
-
if (part.type === "data" && part.data) {
|
|
51
|
+
if ((part.type === "data" || part.data !== void 0) && part.data) {
|
|
43
52
|
return part.data;
|
|
44
53
|
}
|
|
45
|
-
if (part.type === "text" && part.text) {
|
|
54
|
+
if ((part.type === "text" || part.text !== void 0) && part.text) {
|
|
46
55
|
try {
|
|
47
56
|
return JSON.parse(part.text);
|
|
48
57
|
} catch {
|
|
@@ -262,7 +271,7 @@ var TOOL_STOP_CONDITION = stepCountIs(5);
|
|
|
262
271
|
var TOOL_TAG = "tool";
|
|
263
272
|
var LLM_TAG = "llm";
|
|
264
273
|
function extractTextFromMessage(message) {
|
|
265
|
-
return message.parts.filter((p) => p.type === "text" && p.text).map((p) => p.text).join("\n");
|
|
274
|
+
return message.parts.filter((p) => (p.type === "text" || p.text !== void 0) && p.text).map((p) => p.text).join("\n");
|
|
266
275
|
}
|
|
267
276
|
function createLLMProvider(config) {
|
|
268
277
|
const gatewayKey = process.env.AI_GATEWAY_API_KEY;
|
|
@@ -607,6 +616,56 @@ var DEFAULT_LLM_CONFIG = {
|
|
|
607
616
|
import express from "express";
|
|
608
617
|
import { v4 as uuidv4 } from "uuid";
|
|
609
618
|
var A2A_PROTOCOL_VERSION = "0.3";
|
|
619
|
+
function normalizePart(part) {
|
|
620
|
+
if (part.type) return part;
|
|
621
|
+
if (part.text !== void 0) return { type: "text", text: part.text, mediaType: part.mediaType };
|
|
622
|
+
if (part.data !== void 0) return { type: "data", data: part.data, mediaType: part.mediaType };
|
|
623
|
+
if (part.url !== void 0 || part.raw !== void 0) return { type: "file", uri: part.url ?? part.uri, mimeType: part.mediaType };
|
|
624
|
+
return part;
|
|
625
|
+
}
|
|
626
|
+
function normalizeRole(role) {
|
|
627
|
+
if (role === "ROLE_USER" || role === "user") return "user";
|
|
628
|
+
if (role === "ROLE_AGENT" || role === "agent") return "agent";
|
|
629
|
+
return "user";
|
|
630
|
+
}
|
|
631
|
+
function normalizeMessage(msg) {
|
|
632
|
+
const raw = msg;
|
|
633
|
+
return {
|
|
634
|
+
role: normalizeRole(raw.role || "user"),
|
|
635
|
+
messageId: raw.messageId,
|
|
636
|
+
parts: (raw.parts || []).map(normalizePart),
|
|
637
|
+
contextId: raw.contextId,
|
|
638
|
+
taskId: raw.taskId,
|
|
639
|
+
metadata: raw.metadata
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function extractSendParams(params) {
|
|
643
|
+
const rawMessage = params.message || {};
|
|
644
|
+
const message = normalizeMessage(rawMessage);
|
|
645
|
+
const metadata = params.metadata;
|
|
646
|
+
const skillId = params.skill ?? metadata?.skill;
|
|
647
|
+
const contextId = params.contextId ?? message.contextId;
|
|
648
|
+
return { skillId, message, contextId, metadata };
|
|
649
|
+
}
|
|
650
|
+
function toSpecPart(part) {
|
|
651
|
+
const out = {};
|
|
652
|
+
if (part.type === "text" || part.text !== void 0) out.text = part.text ?? "";
|
|
653
|
+
else if (part.type === "data" || part.data !== void 0) out.data = part.data;
|
|
654
|
+
else if (part.type === "file") {
|
|
655
|
+
out.url = part.uri ?? part.url;
|
|
656
|
+
out.mediaType = part.mimeType ?? part.mediaType;
|
|
657
|
+
}
|
|
658
|
+
if (part.mediaType || part.mimeType) out.mediaType = part.mediaType ?? part.mimeType;
|
|
659
|
+
if (part.metadata) out.metadata = part.metadata;
|
|
660
|
+
return out;
|
|
661
|
+
}
|
|
662
|
+
function toSpecArtifact(a) {
|
|
663
|
+
return {
|
|
664
|
+
artifactId: a.artifactId ?? uuidv4(),
|
|
665
|
+
name: a.name,
|
|
666
|
+
parts: a.parts.map(toSpecPart)
|
|
667
|
+
};
|
|
668
|
+
}
|
|
610
669
|
var tasks = /* @__PURE__ */ new Map();
|
|
611
670
|
function generateTaskId() {
|
|
612
671
|
return `task_${Date.now()}_${uuidv4().substring(0, 8)}`;
|
|
@@ -634,40 +693,44 @@ function createA2AServer(options) {
|
|
|
634
693
|
const port = config.port || 9999;
|
|
635
694
|
const host = config.host || "localhost";
|
|
636
695
|
const skills = config.skills || DEFAULT_SKILLS;
|
|
696
|
+
const agentUrl = `http://${host}:${port}/a2a`;
|
|
637
697
|
const agentCard = {
|
|
638
698
|
name: config.name,
|
|
639
699
|
description: config.description || `A2A Agent: ${config.name}`,
|
|
640
|
-
url:
|
|
700
|
+
url: agentUrl,
|
|
701
|
+
supportedInterfaces: [
|
|
702
|
+
{
|
|
703
|
+
url: agentUrl,
|
|
704
|
+
protocolBinding: "JSONRPC",
|
|
705
|
+
protocolVersion: A2A_PROTOCOL_VERSION
|
|
706
|
+
}
|
|
707
|
+
],
|
|
641
708
|
version: config.version || "1.0.0",
|
|
642
709
|
protocolVersion: A2A_PROTOCOL_VERSION,
|
|
643
|
-
defaultInputModes: config.defaultInputModes || ["text", "
|
|
644
|
-
defaultOutputModes: config.defaultOutputModes || ["text", "
|
|
710
|
+
defaultInputModes: config.defaultInputModes || ["text/plain", "application/json"],
|
|
711
|
+
defaultOutputModes: config.defaultOutputModes || ["text/plain", "application/json"],
|
|
645
712
|
provider: config.provider || {
|
|
646
713
|
organization: "Runtype",
|
|
647
714
|
url: "https://runtype.com"
|
|
648
715
|
},
|
|
649
716
|
capabilities: {
|
|
650
717
|
streaming: true,
|
|
651
|
-
pushNotifications: false
|
|
652
|
-
statefulness: "task"
|
|
718
|
+
pushNotifications: false
|
|
653
719
|
},
|
|
654
720
|
skills: skills.map((s) => ({
|
|
655
721
|
id: s.id,
|
|
656
722
|
name: s.name,
|
|
657
723
|
description: s.description,
|
|
658
|
-
inputModes: ["text", "data"],
|
|
659
|
-
outputModes: ["text", "data"],
|
|
660
724
|
tags: s.tags ?? [],
|
|
661
|
-
|
|
662
|
-
}))
|
|
663
|
-
authentication: {
|
|
664
|
-
type: "none"
|
|
665
|
-
}
|
|
725
|
+
examples: []
|
|
726
|
+
}))
|
|
666
727
|
};
|
|
667
|
-
|
|
728
|
+
const agentCardHandler = (_req, res) => {
|
|
668
729
|
res.setHeader("Cache-Control", "public, max-age=3600");
|
|
669
730
|
res.json(agentCard);
|
|
670
|
-
}
|
|
731
|
+
};
|
|
732
|
+
app.get("/.well-known/agent.json", agentCardHandler);
|
|
733
|
+
app.get("/.well-known/agent-card.json", agentCardHandler);
|
|
671
734
|
app.get("/health", (_req, res) => {
|
|
672
735
|
res.json({ status: "healthy", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
673
736
|
});
|
|
@@ -682,17 +745,27 @@ function createA2AServer(options) {
|
|
|
682
745
|
try {
|
|
683
746
|
switch (method) {
|
|
684
747
|
case "tasks/send":
|
|
748
|
+
case "message/send":
|
|
749
|
+
case "SendMessage":
|
|
685
750
|
await handleTasksSend(req, res, id, params, skills, llmConfig, echoMode);
|
|
686
751
|
break;
|
|
687
752
|
case "tasks/sendSubscribe":
|
|
753
|
+
case "message/stream":
|
|
754
|
+
case "SendStreamingMessage":
|
|
688
755
|
await handleTasksSendSubscribe(req, res, id, params, skills, llmConfig, echoMode);
|
|
689
756
|
break;
|
|
690
757
|
case "tasks/get":
|
|
758
|
+
case "GetTask":
|
|
691
759
|
handleTasksGet(res, id, params);
|
|
692
760
|
break;
|
|
693
761
|
case "tasks/cancel":
|
|
762
|
+
case "CancelTask":
|
|
694
763
|
handleTasksCancel(res, id, params);
|
|
695
764
|
break;
|
|
765
|
+
case "tasks/resubscribe":
|
|
766
|
+
case "SubscribeToTask":
|
|
767
|
+
res.json(jsonRpcError(id, JSON_RPC_ERRORS.UNSUPPORTED_OPERATION, "SubscribeToTask is not supported"));
|
|
768
|
+
break;
|
|
696
769
|
case "ping":
|
|
697
770
|
res.json(jsonRpcSuccess(id, { pong: true }));
|
|
698
771
|
break;
|
|
@@ -714,7 +787,7 @@ function createA2AServer(options) {
|
|
|
714
787
|
console.log(`A2A Agent Server: ${config.name}`);
|
|
715
788
|
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
716
789
|
console.log("");
|
|
717
|
-
console.log(` Agent Card: http://${host}:${port}/.well-known/agent.json`);
|
|
790
|
+
console.log(` Agent Card: http://${host}:${port}/.well-known/agent-card.json`);
|
|
718
791
|
console.log(` A2A Endpoint: http://${host}:${port}/a2a`);
|
|
719
792
|
console.log(` Health Check: http://${host}:${port}/health`);
|
|
720
793
|
console.log("");
|
|
@@ -742,23 +815,24 @@ function createA2AServer(options) {
|
|
|
742
815
|
})
|
|
743
816
|
};
|
|
744
817
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
res.json(
|
|
750
|
-
jsonRpcError(id, JSON_RPC_ERRORS.SKILL_NOT_FOUND, `Skill not found: ${skillId}`, {
|
|
751
|
-
availableSkills: skills.map((s) => s.id)
|
|
752
|
-
})
|
|
753
|
-
);
|
|
754
|
-
return;
|
|
818
|
+
function resolveSkill(skillId, skills, echoMode) {
|
|
819
|
+
if (skillId) {
|
|
820
|
+
const found = skills.find((s) => s.id === skillId);
|
|
821
|
+
if (found) return found;
|
|
755
822
|
}
|
|
823
|
+
if (echoMode) return skills.find((s) => s.id === "echo") || skills[0];
|
|
824
|
+
return skills.find((s) => s.id === "chat") || skills[0];
|
|
825
|
+
}
|
|
826
|
+
async function handleTasksSend(_req, res, id, params, skills, llmConfig, echoMode) {
|
|
827
|
+
const { skillId, message, contextId, metadata } = extractSendParams(params);
|
|
828
|
+
const skill = resolveSkill(skillId, skills, echoMode);
|
|
829
|
+
const resolvedContextId = contextId || uuidv4();
|
|
756
830
|
const taskId = generateTaskId();
|
|
757
831
|
const task = {
|
|
758
832
|
id: taskId,
|
|
759
|
-
contextId,
|
|
833
|
+
contextId: resolvedContextId,
|
|
760
834
|
status: "submitted",
|
|
761
|
-
skillId,
|
|
835
|
+
skillId: skill.id,
|
|
762
836
|
requestMessage: message,
|
|
763
837
|
artifacts: [],
|
|
764
838
|
metadata,
|
|
@@ -770,29 +844,29 @@ async function handleTasksSend(_req, res, id, params, skills, llmConfig, echoMod
|
|
|
770
844
|
try {
|
|
771
845
|
const context = {
|
|
772
846
|
taskId,
|
|
773
|
-
contextId,
|
|
847
|
+
contextId: resolvedContextId,
|
|
774
848
|
skill,
|
|
775
849
|
message,
|
|
776
850
|
metadata
|
|
777
851
|
};
|
|
778
852
|
let result;
|
|
779
|
-
if (
|
|
853
|
+
if (skill.id.startsWith("time/")) {
|
|
780
854
|
result = await executeTimeSkill(context);
|
|
781
|
-
} else if (echoMode ||
|
|
855
|
+
} else if (echoMode || skill.id === "echo") {
|
|
782
856
|
result = await executeEcho(context);
|
|
783
857
|
} else {
|
|
784
858
|
result = await executeTask(context, llmConfig, skills);
|
|
785
859
|
}
|
|
786
860
|
task.status = "completed";
|
|
787
|
-
task.artifacts = result.artifacts;
|
|
861
|
+
task.artifacts = result.artifacts || [];
|
|
788
862
|
task.history.push({ status: "completed", message: "Task completed", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
789
863
|
res.json(
|
|
790
864
|
jsonRpcSuccess(id, {
|
|
791
865
|
task: {
|
|
792
866
|
id: taskId,
|
|
793
|
-
contextId,
|
|
794
|
-
status: "completed",
|
|
795
|
-
artifacts: task.artifacts,
|
|
867
|
+
contextId: resolvedContextId,
|
|
868
|
+
status: { state: "completed", timestamp: (/* @__PURE__ */ new Date()).toISOString() },
|
|
869
|
+
artifacts: task.artifacts.map(toSpecArtifact),
|
|
796
870
|
metadata
|
|
797
871
|
}
|
|
798
872
|
})
|
|
@@ -806,22 +880,15 @@ async function handleTasksSend(_req, res, id, params, skills, llmConfig, echoMod
|
|
|
806
880
|
}
|
|
807
881
|
}
|
|
808
882
|
async function handleTasksSendSubscribe(_req, res, id, params, skills, llmConfig, echoMode) {
|
|
809
|
-
const {
|
|
810
|
-
const skill =
|
|
811
|
-
|
|
812
|
-
res.json(
|
|
813
|
-
jsonRpcError(id, JSON_RPC_ERRORS.SKILL_NOT_FOUND, `Skill not found: ${skillId}`, {
|
|
814
|
-
availableSkills: skills.map((s) => s.id)
|
|
815
|
-
})
|
|
816
|
-
);
|
|
817
|
-
return;
|
|
818
|
-
}
|
|
883
|
+
const { skillId, message, contextId, metadata } = extractSendParams(params);
|
|
884
|
+
const skill = resolveSkill(skillId, skills, echoMode);
|
|
885
|
+
const resolvedContextId = contextId || uuidv4();
|
|
819
886
|
const taskId = generateTaskId();
|
|
820
887
|
const task = {
|
|
821
888
|
id: taskId,
|
|
822
|
-
contextId,
|
|
889
|
+
contextId: resolvedContextId,
|
|
823
890
|
status: "submitted",
|
|
824
|
-
skillId,
|
|
891
|
+
skillId: skill.id,
|
|
825
892
|
requestMessage: message,
|
|
826
893
|
artifacts: [],
|
|
827
894
|
metadata,
|
|
@@ -832,72 +899,106 @@ async function handleTasksSendSubscribe(_req, res, id, params, skills, llmConfig
|
|
|
832
899
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
833
900
|
res.setHeader("Connection", "keep-alive");
|
|
834
901
|
res.setHeader("X-Accel-Buffering", "no");
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
data: ${JSON.stringify(
|
|
902
|
+
const sendStreamResponse = (result) => {
|
|
903
|
+
const rpcResponse = { jsonrpc: "2.0", id, result };
|
|
904
|
+
res.write(`data: ${JSON.stringify(rpcResponse)}
|
|
838
905
|
|
|
839
906
|
`);
|
|
840
907
|
};
|
|
841
|
-
|
|
908
|
+
sendStreamResponse({
|
|
909
|
+
task: {
|
|
910
|
+
id: taskId,
|
|
911
|
+
contextId: resolvedContextId,
|
|
912
|
+
status: { state: "submitted", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
913
|
+
}
|
|
914
|
+
});
|
|
842
915
|
task.status = "working";
|
|
843
916
|
task.history.push({ status: "working", message: "Execution started", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
844
|
-
|
|
917
|
+
sendStreamResponse({
|
|
918
|
+
statusUpdate: {
|
|
919
|
+
taskId,
|
|
920
|
+
contextId: resolvedContextId,
|
|
921
|
+
status: { state: "working", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
922
|
+
}
|
|
923
|
+
});
|
|
845
924
|
try {
|
|
846
925
|
const context = {
|
|
847
926
|
taskId,
|
|
848
|
-
contextId,
|
|
927
|
+
contextId: resolvedContextId,
|
|
849
928
|
skill,
|
|
850
929
|
message,
|
|
851
930
|
metadata
|
|
852
931
|
};
|
|
853
|
-
|
|
932
|
+
const artifactId = uuidv4();
|
|
933
|
+
let isFirstChunk = true;
|
|
854
934
|
let fullText = "";
|
|
855
935
|
const callbacks = {
|
|
856
936
|
onChunk: async (text) => {
|
|
857
937
|
fullText += text;
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
938
|
+
sendStreamResponse({
|
|
939
|
+
artifactUpdate: {
|
|
940
|
+
taskId,
|
|
941
|
+
contextId: resolvedContextId,
|
|
942
|
+
artifact: {
|
|
943
|
+
artifactId,
|
|
944
|
+
name: "response",
|
|
945
|
+
parts: [{ text }]
|
|
946
|
+
},
|
|
947
|
+
append: !isFirstChunk,
|
|
865
948
|
lastChunk: false
|
|
866
949
|
}
|
|
867
950
|
});
|
|
868
|
-
|
|
951
|
+
isFirstChunk = false;
|
|
869
952
|
},
|
|
870
953
|
onComplete: async () => {
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
954
|
+
sendStreamResponse({
|
|
955
|
+
artifactUpdate: {
|
|
956
|
+
taskId,
|
|
957
|
+
contextId: resolvedContextId,
|
|
958
|
+
artifact: {
|
|
959
|
+
artifactId,
|
|
960
|
+
name: "response",
|
|
961
|
+
parts: [{ text: "" }]
|
|
962
|
+
},
|
|
877
963
|
append: true,
|
|
878
964
|
lastChunk: true
|
|
879
965
|
}
|
|
880
966
|
});
|
|
881
967
|
task.status = "completed";
|
|
882
|
-
task.artifacts = [{ name: "response", parts: [{ type: "text", text: fullText }] }];
|
|
968
|
+
task.artifacts = [{ artifactId, name: "response", parts: [{ type: "text", text: fullText }] }];
|
|
883
969
|
task.history.push({ status: "completed", message: "Task completed", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
884
|
-
|
|
970
|
+
sendStreamResponse({
|
|
971
|
+
statusUpdate: {
|
|
972
|
+
taskId,
|
|
973
|
+
contextId: resolvedContextId,
|
|
974
|
+
status: { state: "completed", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
975
|
+
}
|
|
976
|
+
});
|
|
885
977
|
res.end();
|
|
886
978
|
},
|
|
887
979
|
onError: async (error) => {
|
|
888
980
|
task.status = "failed";
|
|
889
981
|
task.error = { message: error.message };
|
|
890
982
|
task.history.push({ status: "failed", message: error.message, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
891
|
-
|
|
892
|
-
|
|
983
|
+
sendStreamResponse({
|
|
984
|
+
statusUpdate: {
|
|
985
|
+
taskId,
|
|
986
|
+
contextId: resolvedContextId,
|
|
987
|
+
status: {
|
|
988
|
+
state: "failed",
|
|
989
|
+
message: { role: "agent", parts: [{ text: error.message }] },
|
|
990
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
});
|
|
893
994
|
res.end();
|
|
894
995
|
}
|
|
895
996
|
};
|
|
896
|
-
if (
|
|
997
|
+
if (skill.id.startsWith("time/")) {
|
|
897
998
|
const timeResult = await executeTimeSkill(context);
|
|
898
999
|
await callbacks.onChunk(timeResult.text);
|
|
899
1000
|
await callbacks.onComplete();
|
|
900
|
-
} else if (echoMode ||
|
|
1001
|
+
} else if (echoMode || skill.id === "echo") {
|
|
901
1002
|
await executeEchoStreaming(context, callbacks);
|
|
902
1003
|
} else {
|
|
903
1004
|
await executeTaskStreaming(context, llmConfig, callbacks, skills);
|
|
@@ -907,53 +1008,70 @@ data: ${JSON.stringify(data)}
|
|
|
907
1008
|
task.status = "failed";
|
|
908
1009
|
task.error = { message: errorMessage };
|
|
909
1010
|
task.history.push({ status: "failed", message: errorMessage, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
910
|
-
|
|
911
|
-
|
|
1011
|
+
sendStreamResponse({
|
|
1012
|
+
statusUpdate: {
|
|
1013
|
+
taskId,
|
|
1014
|
+
contextId: resolvedContextId,
|
|
1015
|
+
status: {
|
|
1016
|
+
state: "failed",
|
|
1017
|
+
message: { role: "agent", parts: [{ text: errorMessage }] },
|
|
1018
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
912
1022
|
res.end();
|
|
913
1023
|
}
|
|
914
1024
|
}
|
|
915
1025
|
function handleTasksGet(res, id, params) {
|
|
916
|
-
const
|
|
917
|
-
|
|
1026
|
+
const resolvedTaskId = params.id || params.taskId;
|
|
1027
|
+
if (!resolvedTaskId) {
|
|
1028
|
+
res.json(jsonRpcError(id, JSON_RPC_ERRORS.INVALID_PARAMS, "Missing task id"));
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
const task = tasks.get(resolvedTaskId);
|
|
918
1032
|
if (!task) {
|
|
919
|
-
res.json(jsonRpcError(id, JSON_RPC_ERRORS.TASK_NOT_FOUND, `Task not found: ${
|
|
1033
|
+
res.json(jsonRpcError(id, JSON_RPC_ERRORS.TASK_NOT_FOUND, `Task not found: ${resolvedTaskId}`));
|
|
920
1034
|
return;
|
|
921
1035
|
}
|
|
922
1036
|
const result = {
|
|
923
1037
|
task: {
|
|
924
1038
|
id: task.id,
|
|
925
1039
|
contextId: task.contextId,
|
|
926
|
-
status: task.status,
|
|
927
|
-
artifacts: task.artifacts,
|
|
1040
|
+
status: { state: task.status, timestamp: (/* @__PURE__ */ new Date()).toISOString() },
|
|
1041
|
+
artifacts: task.artifacts.map(toSpecArtifact),
|
|
928
1042
|
metadata: task.metadata
|
|
929
1043
|
}
|
|
930
1044
|
};
|
|
931
|
-
if (task.error) {
|
|
932
|
-
result.task.error = task.error;
|
|
933
|
-
}
|
|
934
|
-
if (includeHistory) {
|
|
935
|
-
result.task.history = task.history;
|
|
936
|
-
}
|
|
937
1045
|
res.json(jsonRpcSuccess(id, result));
|
|
938
1046
|
}
|
|
939
1047
|
function handleTasksCancel(res, id, params) {
|
|
940
|
-
const
|
|
941
|
-
|
|
1048
|
+
const resolvedTaskId = params.id || params.taskId;
|
|
1049
|
+
if (!resolvedTaskId) {
|
|
1050
|
+
res.json(jsonRpcError(id, JSON_RPC_ERRORS.INVALID_PARAMS, "Missing task id"));
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const task = tasks.get(resolvedTaskId);
|
|
942
1054
|
if (!task) {
|
|
943
|
-
res.json(jsonRpcError(id, JSON_RPC_ERRORS.TASK_NOT_FOUND, `Task not found: ${
|
|
1055
|
+
res.json(jsonRpcError(id, JSON_RPC_ERRORS.TASK_NOT_FOUND, `Task not found: ${resolvedTaskId}`));
|
|
944
1056
|
return;
|
|
945
1057
|
}
|
|
946
1058
|
if (["completed", "failed", "canceled"].includes(task.status)) {
|
|
947
|
-
res.json(jsonRpcError(id, JSON_RPC_ERRORS.
|
|
1059
|
+
res.json(jsonRpcError(id, JSON_RPC_ERRORS.TASK_NOT_CANCELABLE, `Task cannot be canceled: already ${task.status}`));
|
|
948
1060
|
return;
|
|
949
1061
|
}
|
|
950
1062
|
task.status = "canceled";
|
|
951
1063
|
task.history.push({
|
|
952
1064
|
status: "canceled",
|
|
953
|
-
message: reason || "Canceled by request",
|
|
1065
|
+
message: params.reason || "Canceled by request",
|
|
954
1066
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
955
1067
|
});
|
|
956
|
-
res.json(jsonRpcSuccess(id, {
|
|
1068
|
+
res.json(jsonRpcSuccess(id, {
|
|
1069
|
+
task: {
|
|
1070
|
+
id: resolvedTaskId,
|
|
1071
|
+
contextId: task.contextId,
|
|
1072
|
+
status: { state: "canceled", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
1073
|
+
}
|
|
1074
|
+
}));
|
|
957
1075
|
}
|
|
958
1076
|
|
|
959
1077
|
// src/client.ts
|
|
@@ -967,13 +1085,10 @@ var A2AClient = class {
|
|
|
967
1085
|
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
968
1086
|
const isA2aBase = this.baseUrl.endsWith("/a2a");
|
|
969
1087
|
this.rpcUrl = isA2aBase ? this.baseUrl : `${this.baseUrl}/a2a`;
|
|
970
|
-
this.agentCardUrl = `${this.baseUrl}/.well-known/agent.json`;
|
|
1088
|
+
this.agentCardUrl = `${this.baseUrl}/.well-known/agent-card.json`;
|
|
971
1089
|
this.apiKey = options.apiKey;
|
|
972
1090
|
this.headers = options.headers || {};
|
|
973
1091
|
}
|
|
974
|
-
/**
|
|
975
|
-
* Get the agent card for discovery
|
|
976
|
-
*/
|
|
977
1092
|
async getAgentCard() {
|
|
978
1093
|
const response = await fetch(this.agentCardUrl, {
|
|
979
1094
|
headers: this.getHeaders()
|
|
@@ -983,15 +1098,12 @@ var A2AClient = class {
|
|
|
983
1098
|
}
|
|
984
1099
|
return response.json();
|
|
985
1100
|
}
|
|
986
|
-
/**
|
|
987
|
-
* Send a task and wait for completion (synchronous)
|
|
988
|
-
*/
|
|
989
1101
|
async sendTask(params) {
|
|
990
1102
|
const request = {
|
|
991
1103
|
jsonrpc: "2.0",
|
|
992
1104
|
id: `req_${Date.now()}`,
|
|
993
|
-
method: "
|
|
994
|
-
params
|
|
1105
|
+
method: "message/send",
|
|
1106
|
+
params: this.toSendMessageRequest(params)
|
|
995
1107
|
};
|
|
996
1108
|
const response = await this.sendJsonRpc(request);
|
|
997
1109
|
if (response.error) {
|
|
@@ -999,17 +1111,14 @@ var A2AClient = class {
|
|
|
999
1111
|
}
|
|
1000
1112
|
return response.result.task;
|
|
1001
1113
|
}
|
|
1002
|
-
/**
|
|
1003
|
-
* Send a task with streaming (SSE)
|
|
1004
|
-
*/
|
|
1005
1114
|
async sendTaskStreaming(params, callbacks) {
|
|
1006
1115
|
const request = {
|
|
1007
1116
|
jsonrpc: "2.0",
|
|
1008
1117
|
id: `req_${Date.now()}`,
|
|
1009
|
-
method: "
|
|
1010
|
-
params
|
|
1118
|
+
method: "message/stream",
|
|
1119
|
+
params: this.toSendMessageRequest(params)
|
|
1011
1120
|
};
|
|
1012
|
-
const response = await fetch(
|
|
1121
|
+
const response = await fetch(this.rpcUrl, {
|
|
1013
1122
|
method: "POST",
|
|
1014
1123
|
headers: {
|
|
1015
1124
|
"Content-Type": "application/json",
|
|
@@ -1032,43 +1141,37 @@ var A2AClient = class {
|
|
|
1032
1141
|
buffer += decoder.decode(value, { stream: true });
|
|
1033
1142
|
const lines = buffer.split("\n");
|
|
1034
1143
|
buffer = lines.pop() || "";
|
|
1035
|
-
let currentEvent = "";
|
|
1036
1144
|
for (const line of lines) {
|
|
1037
|
-
if (line.startsWith("
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
break;
|
|
1055
|
-
case "task/error":
|
|
1056
|
-
callbacks.onError?.(data.error);
|
|
1057
|
-
break;
|
|
1145
|
+
if (!line.startsWith("data: ")) continue;
|
|
1146
|
+
const payload = JSON.parse(line.substring(6));
|
|
1147
|
+
const result = payload.result || payload;
|
|
1148
|
+
if (result.statusUpdate) {
|
|
1149
|
+
const state = result.statusUpdate.status?.state || result.statusUpdate.status;
|
|
1150
|
+
callbacks.onStatus?.(state, result.statusUpdate);
|
|
1151
|
+
} else if (result.artifactUpdate) {
|
|
1152
|
+
const artifact = result.artifactUpdate.artifact;
|
|
1153
|
+
callbacks.onArtifact?.(artifact);
|
|
1154
|
+
if (artifact?.parts) {
|
|
1155
|
+
for (const part of artifact.parts) {
|
|
1156
|
+
const text = part.text ?? (part.type === "text" ? part.text : void 0);
|
|
1157
|
+
if (text) callbacks.onChunk?.(text);
|
|
1158
|
+
}
|
|
1058
1159
|
}
|
|
1160
|
+
} else if (result.task) {
|
|
1161
|
+
const state = result.task.status?.state || result.task.status;
|
|
1162
|
+
if (state) callbacks.onStatus?.(state, result.task);
|
|
1163
|
+
} else if (result.error || payload.error) {
|
|
1164
|
+
callbacks.onError?.(result.error || payload.error);
|
|
1059
1165
|
}
|
|
1060
1166
|
}
|
|
1061
1167
|
}
|
|
1062
1168
|
}
|
|
1063
|
-
|
|
1064
|
-
* Get task status
|
|
1065
|
-
*/
|
|
1066
|
-
async getTask(taskId, includeHistory = false) {
|
|
1169
|
+
async getTask(taskId, historyLength) {
|
|
1067
1170
|
const request = {
|
|
1068
1171
|
jsonrpc: "2.0",
|
|
1069
1172
|
id: `req_${Date.now()}`,
|
|
1070
|
-
method: "
|
|
1071
|
-
params: { taskId,
|
|
1173
|
+
method: "GetTask",
|
|
1174
|
+
params: { id: taskId, historyLength }
|
|
1072
1175
|
};
|
|
1073
1176
|
const response = await this.sendJsonRpc(request);
|
|
1074
1177
|
if (response.error) {
|
|
@@ -1076,15 +1179,12 @@ var A2AClient = class {
|
|
|
1076
1179
|
}
|
|
1077
1180
|
return response.result.task;
|
|
1078
1181
|
}
|
|
1079
|
-
/**
|
|
1080
|
-
* Cancel a task
|
|
1081
|
-
*/
|
|
1082
1182
|
async cancelTask(taskId, reason) {
|
|
1083
1183
|
const request = {
|
|
1084
1184
|
jsonrpc: "2.0",
|
|
1085
1185
|
id: `req_${Date.now()}`,
|
|
1086
|
-
method: "
|
|
1087
|
-
params: { taskId, reason }
|
|
1186
|
+
method: "CancelTask",
|
|
1187
|
+
params: { id: taskId, metadata: reason ? { reason } : void 0 }
|
|
1088
1188
|
};
|
|
1089
1189
|
const response = await this.sendJsonRpc(request);
|
|
1090
1190
|
if (response.error) {
|
|
@@ -1093,8 +1193,23 @@ var A2AClient = class {
|
|
|
1093
1193
|
return response.result.task;
|
|
1094
1194
|
}
|
|
1095
1195
|
/**
|
|
1096
|
-
*
|
|
1196
|
+
* Convert legacy TasksSendParams to spec SendMessageRequest format
|
|
1097
1197
|
*/
|
|
1198
|
+
toSendMessageRequest(params) {
|
|
1199
|
+
return {
|
|
1200
|
+
message: {
|
|
1201
|
+
messageId: `msg_${Date.now()}`,
|
|
1202
|
+
role: "user",
|
|
1203
|
+
parts: params.message.parts,
|
|
1204
|
+
contextId: params.contextId,
|
|
1205
|
+
taskId: params.message.taskId
|
|
1206
|
+
},
|
|
1207
|
+
metadata: {
|
|
1208
|
+
...params.metadata,
|
|
1209
|
+
...params.skill ? { skill: params.skill } : {}
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1098
1213
|
async sendJsonRpc(request) {
|
|
1099
1214
|
const response = await fetch(this.rpcUrl, {
|
|
1100
1215
|
method: "POST",
|
|
@@ -1109,9 +1224,6 @@ var A2AClient = class {
|
|
|
1109
1224
|
}
|
|
1110
1225
|
return response.json();
|
|
1111
1226
|
}
|
|
1112
|
-
/**
|
|
1113
|
-
* Get headers for requests
|
|
1114
|
-
*/
|
|
1115
1227
|
getHeaders() {
|
|
1116
1228
|
const headers = { ...this.headers };
|
|
1117
1229
|
if (this.apiKey) {
|
|
@@ -1151,4 +1263,4 @@ export {
|
|
|
1151
1263
|
A2AClient,
|
|
1152
1264
|
createRuntypeA2AClient
|
|
1153
1265
|
};
|
|
1154
|
-
//# sourceMappingURL=chunk-
|
|
1266
|
+
//# sourceMappingURL=chunk-EY4P4D5Y.js.map
|