Skip to content

Commit 27e6eb2

Browse files
committed
Updated to v2.0.2
1 parent a650d04 commit 27e6eb2

File tree

2 files changed

+96
-36
lines changed

2 files changed

+96
-36
lines changed

A2AApp.js

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
* This is used for building both an Agent2Agent (A2A) server and an A2A client with Google Apps Script.
44
*
55
* Author: Kanshi Tanaike
6-
* 20250529 10:04
7-
* version 2.0.1
6+
* 20250618 10:40
7+
* version 2.0.
88
* @class
99
*/
1010
class A2AApp {
@@ -24,6 +24,9 @@ class A2AApp {
2424
/** @private */
2525
this.model = "models/gemini-2.0-flash"; // or "models/gemini-2.5-flash-preview-04-17"
2626

27+
/** @private */
28+
this.jsonrpc = "2.0";
29+
2730
/** @private */
2831
this.date = new Date();
2932

@@ -158,7 +161,7 @@ class A2AApp {
158161
} catch ({ stack }) {
159162
console.error(stack);
160163
const err = "Internal server error";
161-
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Error message: ${stack}` }, "jsonrpc": "2.0", id };
164+
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Error message: ${stack}` }, "jsonrpc": this.jsonrpc, id };
162165
this.values.push([this.date, null, id, "server --> client", JSON.stringify(errObj)]);
163166
if (this.log) {
164167
this.log_();
@@ -170,7 +173,7 @@ class A2AApp {
170173
} else {
171174
console.error("Timeout.");
172175
const err = "Internal server error";
173-
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Error message: Timeout.` }, "jsonrpc": "2.0", id };
176+
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Error message: Timeout.` }, "jsonrpc": this.jsonrpc, id };
174177
this.values.push([this.date, null, id, "server --> client", JSON.stringify(errObj)]);
175178
if (this.log) {
176179
this.log_();
@@ -295,18 +298,87 @@ class A2AApp {
295298
if (this.accessKey && eventObject.parameter.accessKey && eventObject.parameter.accessKey != this.accessKey) {
296299
this.values.push([this.date, method, id, "At server", "Invalid accessKey."]);
297300
const err = "Authorization failed";
298-
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Invalid access key.` }, "jsonrpc": "2.0", id };
301+
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Invalid access key.` }, "jsonrpc": this.jsonrpc, id };
299302
this.values.push([this.date, method, id, "server --> client", JSON.stringify(errObj)]);
300303
return this.createContent_(errObj);
301304
}
302305

303-
if (method == "tasks/send" && functions) {
306+
if (method == "message/send" && functions) {
307+
let resObj;
308+
let messageId;
309+
try {
310+
if (typeof functions != "function") {
311+
const err = "Internal server error";
312+
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Invalid functions.` }, "jsonrpc": this.jsonrpc, id };
313+
this.values.push([this.date, method, id, "server --> client", JSON.stringify(errObj)]);
314+
return this.createContent_(errObj);
315+
}
316+
const { params } = obj;
317+
const { message } = params;
318+
messageId = params.messageId;
319+
const prompt = message.parts[0].text;
320+
321+
const { result, history } = this.processAgents_({
322+
apiKey,
323+
prompt,
324+
functions: functions(),
325+
fileAsBlob: true,
326+
agentCards,
327+
});
328+
for (let i = 0; i < result.length; i++) {
329+
if (typeof result[i] == "string") {
330+
result[i] = { type: "text", kind: "text", text: result[i] };
331+
}
332+
}
333+
const { messageParts } = result.reduce((o, e, i) => {
334+
const type = e.type;
335+
if (type == "text") {
336+
const gg = new GeminiWithFiles({ apiKey, model: this.model, history });
337+
const res = gg.generateContent({
338+
parts: [
339+
{ text: `Summarize answers by considering the question.` },
340+
{ text: `<Question>${prompt}</Question>` },
341+
{ text: `<Answers>${e[e.type]}</Answers>` }
342+
]
343+
});
344+
o.messageParts.push({ type: "text", kind: "text", text: res });
345+
o.artifacts.push({ name: "Answer", index: i, parts: [{ type: "text", kind: "text", text: res }] });
346+
} else {
347+
if (type != "file" && type != "data") {
348+
o.messageParts.push(e);
349+
} else {
350+
o.messageParts.push({ type: "text", kind: "text", text: `The data "${e[type].name}" was downloaded.` });
351+
}
352+
o.artifacts.push({ name: "Answer", index: i, parts: [e] });
353+
}
354+
return o;
355+
}, { artifacts: [], messageParts: [] });
356+
resObj = {
357+
jsonrpc: this.jsonrpc,
358+
result: {
359+
kind: "message",
360+
messageId,
361+
parts: messageParts,
362+
role: "agent"
363+
},
364+
id
365+
};
366+
} catch ({ stack }) {
367+
console.error(stack);
368+
const err = "Internal server error";
369+
resObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Error message: ${stack}` }, "jsonrpc": this.jsonrpc, id };
370+
}
371+
372+
this.values.push([this.date, method, id, "server --> client", JSON.stringify(resObj)]);
373+
return this.createContent_(resObj);
374+
375+
} else if (method == "tasks/send" && functions) {
304376
let resObj;
305377
let paramsId, sessionId;
306378
try {
307379
if (typeof functions != "function") {
308380
const err = "Internal server error";
309-
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Invalid functions.` }, "jsonrpc": "2.0", id };
381+
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Invalid functions.` }, "jsonrpc": this.jsonrpc, id };
310382
this.values.push([this.date, method, id, "server --> client", JSON.stringify(errObj)]);
311383
return this.createContent_(errObj);
312384
}
@@ -325,7 +397,7 @@ class A2AApp {
325397
});
326398
for (let i = 0; i < result.length; i++) {
327399
if (typeof result[i] == "string") {
328-
result[i] = { type: "text", text: result[i] };
400+
result[i] = { type: "text", kind: "text", text: result[i] };
329401
}
330402
}
331403
const { artifacts, messageParts } = result.reduce((o, e, i) => {
@@ -339,22 +411,23 @@ class A2AApp {
339411
{ text: `<Answers>${e[e.type]}</Answers>` }
340412
]
341413
});
342-
o.messageParts.push({ type: "text", text: res });
343-
o.artifacts.push({ name: "Answer", index: i, parts: [{ type: "text", text: res }] });
414+
o.messageParts.push({ type: "text", kind: "text", text: res });
415+
o.artifacts.push({ name: "Answer", index: i, parts: [{ type: "text", kind: "text", text: res }] });
344416
} else {
345417
if (type != "file" && type != "data") {
346418
o.messageParts.push(e);
347419
} else {
348-
o.messageParts.push({ type: "text", text: `The data "${e[type].name}" was downloaded.` });
420+
o.messageParts.push({ type: "text", kind: "text", text: `The data "${e[type].name}" was downloaded.` });
349421
}
350422
o.artifacts.push({ name: "Answer", index: i, parts: [e] });
351423
}
352424
return o;
353425
}, { artifacts: [], messageParts: [] });
354426

355427
resObj = {
356-
jsonrpc: "2.0",
428+
jsonrpc: this.jsonrpc,
357429
result: {
430+
kind: "task",
358431
id: paramsId,
359432
sessionId: sessionId,
360433
status: {
@@ -368,31 +441,14 @@ class A2AApp {
368441
};
369442
} catch ({ stack }) {
370443
console.error(stack);
371-
resObj = {
372-
jsonrpc: "2.0",
373-
result: {
374-
id: paramsId,
375-
sessionId: sessionId,
376-
status: {
377-
state: this.TaskState.failed,
378-
message: { role: "agent", parts: [{ type: "text", text: stack }] },
379-
timestamp: this.date.toISOString()
380-
},
381-
artifacts: [
382-
{
383-
name: "Answer",
384-
index: 0,
385-
parts: [{ type: "text", text: stack }]
386-
}
387-
]
388-
},
389-
id,
390-
};
444+
const err = "Internal server error";
445+
resObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Error message: ${stack}` }, "jsonrpc": this.jsonrpc, id };
391446
}
392447

393448
this.values.push([this.date, method, id, "server --> client", JSON.stringify(resObj)]);
394449
return this.createContent_(resObj);
395450
}
451+
396452
return null;
397453
}
398454

@@ -517,9 +573,9 @@ class A2AApp {
517573
const id2 = Utilities.getUuid();
518574
const id3 = Utilities.getUuid();
519575
const resObj = {
520-
jsonrpc: '2.0',
576+
jsonrpc: this.jsonrpc,
521577
id: id1,
522-
method: 'tasks/send',
578+
method: "tasks/send",
523579
params:
524580
{
525581
id: id2,
@@ -714,7 +770,7 @@ class A2AApp {
714770
const orderAr = g.generateContent({ q: textPrompt });
715771
if (!Array.isArray(orderAr) || orderAr.length == 0) {
716772
const err = "Internal server error";
717-
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Try again.` }, "jsonrpc": "2.0", id };
773+
const errObj = { "error": { "code": this.ErrorCode[err], "message": `${err}. Try again.` }, "jsonrpc": this.jsonrpc, id };
718774
this.values.push([this.date, null, null, "Client side", JSON.stringify(errObj)]);
719775
return errObj;
720776
}
@@ -903,4 +959,4 @@ class A2AApp {
903959
.join("&")
904960
);
905961
}
906-
}
962+
}

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,5 +394,9 @@ Once the above steps are completed, access `http://0.0.0.0:12000/` or `http://lo
394394

395395
1. From v2.0.1, A2AApp can also be used as a library. [Ref](https://github.com/tanaikech/A2AApp/tree/master/Use_A2AApp_as_library)
396396

397+
- v2.0.2 (June 18, 2025)
398+
399+
1. A bug was removed.
400+
397401
[TOP](#top)
398402

0 commit comments

Comments
 (0)