@artinet/sdk 0.6.0-preview.1 → 0.6.0-preview.2
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 +1 -1
- package/dist/browser/client/a2a-client.js +4 -4
- package/dist/browser/config/index.d.ts +1 -1
- package/dist/browser/config/index.js +1 -1
- package/dist/browser/create/agentcard-builder.d.ts +47 -0
- package/dist/browser/create/agentcard-builder.js +65 -0
- package/dist/browser/create/base.d.ts +4 -0
- package/dist/browser/create/base.js +1 -0
- package/dist/browser/create/describe.d.ts +8 -0
- package/dist/browser/create/describe.js +8 -0
- package/dist/browser/create/message-builder.d.ts +78 -0
- package/dist/browser/create/message-builder.js +108 -0
- package/dist/browser/create/part-builder.d.ts +60 -0
- package/dist/browser/create/part-builder.js +81 -0
- package/dist/browser/create/task-builder.d.ts +251 -0
- package/dist/browser/create/task-builder.js +379 -0
- package/dist/browser/transport/rpc/parser.d.ts +1 -1
- package/dist/browser/transport/rpc/parser.js +2 -1
- package/dist/browser/types/a2a/a2a.d.ts +7 -3
- package/dist/browser/types/a2a/index.d.ts +3 -1
- package/dist/browser/types/a2a/index.js +0 -1
- package/dist/browser/utils/common/constants.d.ts +0 -5
- package/dist/browser/utils/common/constants.js +0 -27
- package/dist/browser/utils/common/errors.d.ts +57 -1
- package/dist/browser/utils/common/errors.js +68 -15
- package/dist/client/a2a-client.js +4 -4
- package/dist/config/default.d.ts +1 -1
- package/dist/config/default.js +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +1 -1
- package/dist/create/agent-builder.d.ts +77 -0
- package/dist/create/agent-builder.js +20 -0
- package/dist/create/agentcard-builder.d.ts +47 -0
- package/dist/create/agentcard-builder.js +66 -0
- package/dist/create/base.d.ts +4 -0
- package/dist/create/base.js +1 -0
- package/dist/create/create.d.ts +762 -0
- package/dist/create/create.js +556 -0
- package/dist/create/describe.d.ts +8 -0
- package/dist/create/describe.js +8 -0
- package/dist/create/index.d.ts +4 -0
- package/dist/create/index.js +4 -0
- package/dist/create/message-builder.d.ts +78 -0
- package/dist/create/message-builder.js +110 -0
- package/dist/create/part-builder.d.ts +60 -0
- package/dist/create/part-builder.js +84 -0
- package/dist/create/status-builder.d.ts +26 -0
- package/dist/create/status-builder.js +46 -0
- package/dist/create/task-builder.d.ts +251 -0
- package/dist/create/task-builder.js +384 -0
- package/dist/create/transform.d.ts +16 -0
- package/dist/create/transform.js +106 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/server/express/errors.js +4 -8
- package/dist/server/express/middeware.js +17 -38
- package/dist/server/express/server.d.ts +6 -1
- package/dist/server/express/server.js +30 -12
- package/dist/services/a2a/execute.d.ts +5 -0
- package/dist/services/a2a/execute.js +7 -0
- package/dist/services/a2a/factory/context.d.ts +1 -1
- package/dist/services/a2a/factory/context.js +2 -3
- package/dist/services/a2a/factory/handler.js +3 -3
- package/dist/services/a2a/factory/index.d.ts +0 -1
- package/dist/services/a2a/factory/index.js +0 -1
- package/dist/services/a2a/factory/service.d.ts +2 -2
- package/dist/services/a2a/factory/service.js +2 -2
- package/dist/services/a2a/factory/state-machine.d.ts +1 -1
- package/dist/services/a2a/factory/state-machine.js +30 -8
- package/dist/services/a2a/handlers/artifact.d.ts +2 -5
- package/dist/services/a2a/handlers/artifact.js +21 -32
- package/dist/services/a2a/handlers/cancel-task.js +7 -5
- package/dist/services/a2a/handlers/resubscribe-task.d.ts +10 -2
- package/dist/services/a2a/handlers/resubscribe-task.js +21 -18
- package/dist/services/a2a/handlers/send-message.js +6 -10
- package/dist/services/a2a/handlers/stream-message.d.ts +10 -2
- package/dist/services/a2a/handlers/stream-message.js +5 -1
- package/dist/services/a2a/handlers/update.js +11 -6
- package/dist/services/a2a/helpers/content.d.ts +5 -1
- package/dist/services/a2a/helpers/content.js +5 -1
- package/dist/services/a2a/helpers/index.d.ts +2 -2
- package/dist/services/a2a/helpers/index.js +2 -2
- package/dist/services/a2a/index.d.ts +1 -1
- package/dist/services/a2a/index.js +1 -1
- package/dist/services/a2a/managers.js +7 -1
- package/dist/services/a2a/service.d.ts +6 -2
- package/dist/services/a2a/service.js +52 -59
- package/dist/services/a2a/state-machine.d.ts +3 -3
- package/dist/services/a2a/state-machine.js +2 -0
- package/dist/transport/rpc/parser.d.ts +1 -1
- package/dist/transport/rpc/parser.js +2 -1
- package/dist/types/a2a/a2a.d.ts +7 -3
- package/dist/types/a2a/index.d.ts +3 -1
- package/dist/types/a2a/index.js +0 -1
- package/dist/utils/common/constants.d.ts +0 -5
- package/dist/utils/common/constants.js +0 -27
- package/dist/utils/common/errors.d.ts +57 -1
- package/dist/utils/common/errors.js +68 -15
- package/dist/utils/common/parse.d.ts +1 -1
- package/dist/utils/common/schema-validation.d.ts +1 -1
- package/package.json +7 -4
- package/dist/browser/services/a2a/helpers/message-builder.d.ts +0 -17
- package/dist/browser/services/a2a/helpers/message-builder.js +0 -66
- package/dist/browser/types/a2a/builder.d.ts +0 -43
- package/dist/browser/types/a2a/builder.js +0 -5
- package/dist/services/a2a/factory/builder.d.ts +0 -292
- package/dist/services/a2a/factory/builder.js +0 -370
- package/dist/services/a2a/helpers/agentcard-builder.d.ts +0 -11
- package/dist/services/a2a/helpers/agentcard-builder.js +0 -27
- package/dist/services/a2a/helpers/message-builder.d.ts +0 -17
- package/dist/services/a2a/helpers/message-builder.js +0 -66
- package/dist/types/a2a/builder.d.ts +0 -43
- package/dist/types/a2a/builder.js +0 -5
|
@@ -3,26 +3,24 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import express from "express";
|
|
6
|
-
import { INVALID_REQUEST, PARSE_ERROR } from "../../utils/index.js";
|
|
7
6
|
import { createAgent, Service, } from "../../services/index.js";
|
|
8
7
|
import cors from "cors";
|
|
9
8
|
import { jsonRPCMiddleware } from "./middeware.js";
|
|
10
9
|
import { errorHandler } from "./errors.js";
|
|
10
|
+
import { logger } from "../../config/index.js";
|
|
11
|
+
import { A2AError } from "@a2a-js/sdk/server";
|
|
12
|
+
import { formatJson } from "../../utils/common/utils.js";
|
|
11
13
|
export function rpcParser(req, res, next) {
|
|
12
14
|
express.json()(req, res, (err) => {
|
|
13
15
|
if (!req.body || typeof req.body !== "object") {
|
|
14
|
-
return next(
|
|
15
|
-
data: { message: "Invalid request body" },
|
|
16
|
-
}));
|
|
16
|
+
return next(A2AError.parseError(`Invalid request body: ${formatJson(req.body)}`));
|
|
17
17
|
}
|
|
18
18
|
if (err) {
|
|
19
19
|
if (err instanceof SyntaxError &&
|
|
20
20
|
"status" in err &&
|
|
21
21
|
err.status === 400 &&
|
|
22
22
|
"body" in err) {
|
|
23
|
-
return next(
|
|
24
|
-
data: err.message,
|
|
25
|
-
}));
|
|
23
|
+
return next(A2AError.parseError(`Invalid request body: ${formatJson(req.body)}`));
|
|
26
24
|
}
|
|
27
25
|
return next(err);
|
|
28
26
|
}
|
|
@@ -46,7 +44,11 @@ const ensureAgent = (agentOrParams) => {
|
|
|
46
44
|
}
|
|
47
45
|
throw new Error("invalid agent or params");
|
|
48
46
|
};
|
|
49
|
-
|
|
47
|
+
const registerAgent = async (agentCard) => {
|
|
48
|
+
logger.debug("registerAgent: not implemented", { agentCard });
|
|
49
|
+
return Promise.resolve(agentCard);
|
|
50
|
+
};
|
|
51
|
+
export function createAgentServer({ app = express(), basePath = "/", agentCardPath = "/.well-known/agent-card.json", agent, corsOptions, extendedAgentCard, register = false, port, }) {
|
|
50
52
|
const agentInstance = ensureAgent(agent);
|
|
51
53
|
app.use(cors(corsOptions));
|
|
52
54
|
if (agentCardPath !== "/.well-known/agent-card.json") {
|
|
@@ -72,10 +74,10 @@ export function createAgentServer({ app = express(), basePath = "/", agentCardPa
|
|
|
72
74
|
//a standard express middleware to handle json-rpc requests
|
|
73
75
|
app.post(basePath, rpcParser, async (req, res, next) => {
|
|
74
76
|
const { jsonrpc } = req.body;
|
|
75
|
-
if (jsonrpc
|
|
76
|
-
return
|
|
77
|
+
if (jsonrpc !== "2.0") {
|
|
78
|
+
return next(A2AError.invalidRequest("Invalid JSON-RPC request"));
|
|
77
79
|
}
|
|
78
|
-
|
|
80
|
+
return await jsonRPCMiddleware(agentInstance, req, res, next, extendedAgentCard);
|
|
79
81
|
});
|
|
80
82
|
app.use(errorHandler);
|
|
81
83
|
/** this is an example of using trpc as express middleware
|
|
@@ -94,5 +96,21 @@ export function createAgentServer({ app = express(), basePath = "/", agentCardPa
|
|
|
94
96
|
);
|
|
95
97
|
* we could also use trpc directly or any other transport layer
|
|
96
98
|
*/
|
|
97
|
-
|
|
99
|
+
const start = (_port) => {
|
|
100
|
+
try {
|
|
101
|
+
const listenPort = _port ?? port;
|
|
102
|
+
const server = app.listen(listenPort, () => {
|
|
103
|
+
logger.info(`Agent server started on port ${listenPort}`);
|
|
104
|
+
});
|
|
105
|
+
if (register) {
|
|
106
|
+
registerAgent(agentInstance.agentCard);
|
|
107
|
+
}
|
|
108
|
+
return server;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
logger.error(`Failed to start agent server`, error);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return { app, agent: agentInstance, start };
|
|
98
116
|
}
|
|
@@ -3,4 +3,9 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { A2A } from "../../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Our universal executor for {@link A2A.Engine}.
|
|
8
|
+
* @param engine - {@link A2A.Engine} to execute.
|
|
9
|
+
* @param context - {@link A2A.Context} provided to the engine.
|
|
10
|
+
*/
|
|
6
11
|
export declare const execute: (engine: A2A.Engine, context: A2A.Context) => Promise<void>;
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* Copyright 2025 The Artinet Project
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Our universal executor for {@link A2A.Engine}.
|
|
7
|
+
* @param engine - {@link A2A.Engine} to execute.
|
|
8
|
+
* @param context - {@link A2A.Context} provided to the engine.
|
|
9
|
+
*/
|
|
5
10
|
export const execute = async (engine, context) => {
|
|
6
11
|
try {
|
|
7
12
|
if (context.publisher.onStart) {
|
|
@@ -16,7 +21,9 @@ export const execute = async (engine, context) => {
|
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
catch (error) {
|
|
24
|
+
/* onError triggers completion internally */
|
|
19
25
|
await context.publisher.onError(error);
|
|
26
|
+
/* rethrow the error to be handled by the caller */
|
|
20
27
|
throw error;
|
|
21
28
|
}
|
|
22
29
|
finally {
|
|
@@ -6,7 +6,7 @@ import { A2A } from "../../../types/index.js";
|
|
|
6
6
|
export declare function createBaseContext({ contextId, service, task, overrides, abortSignal, }: {
|
|
7
7
|
contextId: string;
|
|
8
8
|
service: A2A.Service;
|
|
9
|
-
task
|
|
9
|
+
task: A2A.Task;
|
|
10
10
|
overrides?: Partial<Omit<A2A.EventConsumer, "contextId">>;
|
|
11
11
|
abortSignal?: AbortSignal;
|
|
12
12
|
}): A2A.BaseContext;
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
import { createStateMachine } from "./state-machine.js";
|
|
18
18
|
import { v4 as uuidv4 } from "uuid";
|
|
19
19
|
export function createBaseContext({ contextId = uuidv4(), service, task, overrides, abortSignal = new AbortController().signal, }) {
|
|
20
|
-
const isCancelled = async () => (await service.cancellations.has(task
|
|
21
|
-
abortSignal.aborted;
|
|
20
|
+
const isCancelled = async () => (await service.cancellations.has(task.id)) || abortSignal.aborted;
|
|
22
21
|
const getState = async (args) => args ? await service.tasks.get(args) : task;
|
|
23
22
|
const context = {
|
|
24
23
|
contextId: contextId,
|
|
@@ -34,7 +33,7 @@ export function createContext({ baseContext, taskId, messenger, extensions, refe
|
|
|
34
33
|
const getTask = async () => baseContext.publisher.currentTask;
|
|
35
34
|
const context = {
|
|
36
35
|
...baseContext,
|
|
37
|
-
taskId
|
|
36
|
+
taskId,
|
|
38
37
|
userMessage: messenger.message,
|
|
39
38
|
messages: messenger,
|
|
40
39
|
getTask,
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Copyright 2025 The Artinet Project
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { getTask, cancelTask, sendMessage,
|
|
5
|
+
import { getTask, cancelTask, sendMessage, sendMessageStream, subscribeToTask, } from "../handlers/index.js";
|
|
6
6
|
export function createHandler(methods) {
|
|
7
7
|
return {
|
|
8
8
|
getTask: methods?.getTask ?? getTask,
|
|
9
9
|
cancelTask: methods?.cancelTask ?? cancelTask,
|
|
10
10
|
sendMessage: methods?.sendMessage ?? sendMessage,
|
|
11
|
-
streamMessage: methods?.streamMessage ??
|
|
12
|
-
resubscribe: methods?.resubscribe ??
|
|
11
|
+
streamMessage: methods?.streamMessage ?? sendMessageStream,
|
|
12
|
+
resubscribe: methods?.resubscribe ?? subscribeToTask,
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import * as describe from "../../../create/agentcard-builder.js";
|
|
1
2
|
import { A2A } from "../../../types/index.js";
|
|
2
3
|
import { Service } from "../service.js";
|
|
3
|
-
export type AgentCardParams = (Partial<A2A.AgentCard> & Required<Pick<A2A.AgentCard, "name">>) | string;
|
|
4
4
|
export interface ServiceParams {
|
|
5
|
-
agentCard: AgentCardParams;
|
|
5
|
+
agentCard: describe.AgentCardParams;
|
|
6
6
|
engine: A2A.Engine;
|
|
7
7
|
contexts?: A2A.Contexts;
|
|
8
8
|
streams?: A2A.Streams;
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { createHandler } from "./handler.js";
|
|
6
|
-
import
|
|
6
|
+
import * as describe from "../../../create/agentcard-builder.js";
|
|
7
7
|
import { Service } from "../service.js";
|
|
8
8
|
import { Contexts, Streams, Connections, Cancellations, Tasks, } from "../managers.js";
|
|
9
9
|
export function createService(params) {
|
|
10
|
-
return new Service(
|
|
10
|
+
return new Service(describe.card(params.agentCard), params.engine, params.connections ?? new Connections(), params.cancellations ?? new Cancellations(), params.tasks ?? new Tasks(), params.contexts ?? new Contexts(), params.streams ?? new Streams(), createHandler(params.methods), params.overrides);
|
|
11
11
|
}
|
|
12
12
|
export const createAgent = createService;
|
|
@@ -6,6 +6,6 @@ import { A2A } from "../../../types/index.js";
|
|
|
6
6
|
export declare function createStateMachine({ contextId, service, task: currentTask, overrides, }: {
|
|
7
7
|
contextId: string;
|
|
8
8
|
service: A2A.Service;
|
|
9
|
-
task
|
|
9
|
+
task: A2A.Task;
|
|
10
10
|
overrides?: Partial<Omit<A2A.EventConsumer, "contextId">>;
|
|
11
11
|
}): A2A.EventPublisher;
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { StateMachine } from "../state-machine.js";
|
|
6
6
|
import { logger } from "../../../config/index.js";
|
|
7
|
-
import
|
|
7
|
+
import * as describe from "../../../create/describe.js";
|
|
8
|
+
import { TASK_NOT_FOUND } from "../../../utils/index.js";
|
|
8
9
|
import assert from "assert";
|
|
9
10
|
export function createStateMachine({ contextId, service, task: currentTask, overrides, }) {
|
|
10
11
|
const handler = {
|
|
@@ -25,7 +26,11 @@ export function createStateMachine({ contextId, service, task: currentTask, over
|
|
|
25
26
|
logger.info(`onCancel[ctx:${contextId}]:`, "cancellation triggered");
|
|
26
27
|
logger.debug(`onCancel[ctx:${contextId}]:`, "arguments", update, task);
|
|
27
28
|
await service.cancellations.set(task.id);
|
|
28
|
-
const cancellation =
|
|
29
|
+
const cancellation = describe.update.canceled({
|
|
30
|
+
taskId: task.id,
|
|
31
|
+
contextId: task.contextId,
|
|
32
|
+
message: update.status?.message,
|
|
33
|
+
});
|
|
29
34
|
await service.tasks.update((await service.contexts.get(contextId)), cancellation);
|
|
30
35
|
},
|
|
31
36
|
onUpdate: async (update, task) => {
|
|
@@ -43,17 +48,34 @@ export function createStateMachine({ contextId, service, task: currentTask, over
|
|
|
43
48
|
logger.error(`onError[ctx:${contextId}]:`, new Error("task not found"));
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
|
-
const errorUpdate =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
51
|
+
const errorUpdate = describe.update.failed({
|
|
52
|
+
taskId: task.id,
|
|
53
|
+
contextId,
|
|
54
|
+
message: describe.message({
|
|
55
|
+
messageId: "failed-update",
|
|
56
|
+
parts: [
|
|
57
|
+
{
|
|
58
|
+
kind: "text",
|
|
59
|
+
text: error instanceof Error ? error.message : String(error),
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
const context = await service.contexts.get(contextId);
|
|
65
|
+
if (!context) {
|
|
66
|
+
logger.error(`onError[ctx:${contextId}]:`, new Error("context not found"));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
await service.tasks.update(context, errorUpdate).catch((error) => {
|
|
50
70
|
//we capture errors thrown during error handling to ensure we trigger completion gracefully
|
|
51
|
-
logger.error(`onError[ctx:${contextId}]:`, error);
|
|
71
|
+
logger.error(`onError: task update error[ctx:${contextId}]:`, error);
|
|
52
72
|
});
|
|
73
|
+
// we trigger completion here to ensure the context is cleaned up
|
|
74
|
+
await context.publisher.onComplete();
|
|
53
75
|
},
|
|
54
76
|
onComplete: async (task) => {
|
|
55
77
|
assert(task.contextId === contextId, "context mismatch");
|
|
56
|
-
logger.info(`onComplete[ctx:${contextId}]
|
|
78
|
+
logger.info(`onComplete[ctx:${contextId}]: `, { taskId: task.id });
|
|
57
79
|
await service.cancellations.delete(task.id);
|
|
58
80
|
await service.connections.delete(task.contextId);
|
|
59
81
|
await service.contexts.delete(task.contextId);
|
|
@@ -3,8 +3,5 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { A2A } from "../../../types/index.js";
|
|
6
|
-
export declare function
|
|
7
|
-
|
|
8
|
-
replaced: boolean;
|
|
9
|
-
};
|
|
10
|
-
export declare function processArtifactUpdate(append: boolean, artifacts: A2A.Artifact[], artifactUpdate: A2A.Artifact): A2A.Artifact[];
|
|
6
|
+
export declare function updateArtifact(_artifact: A2A.Artifact, update: A2A.TaskArtifactUpdateEvent): A2A.Artifact;
|
|
7
|
+
export declare function upsertArtifact(artifacts: A2A.Artifact[], update: A2A.TaskArtifactUpdateEvent): A2A.Artifact[];
|
|
@@ -2,38 +2,27 @@
|
|
|
2
2
|
* Copyright 2025 The Artinet Project
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
export function
|
|
6
|
-
if (append)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (artifactUpdate.name) {
|
|
19
|
-
existingArtifact.name = artifactUpdate.name;
|
|
20
|
-
}
|
|
21
|
-
artifacts[index] = existingArtifact;
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
artifacts[index] = { ...artifactUpdate };
|
|
25
|
-
}
|
|
26
|
-
return { artifacts, replaced: true };
|
|
5
|
+
export function updateArtifact(_artifact, update) {
|
|
6
|
+
if (!update.append)
|
|
7
|
+
return update.artifact;
|
|
8
|
+
const artifactUpdate = update.artifact;
|
|
9
|
+
const artifact = _artifact;
|
|
10
|
+
artifact.metadata = {
|
|
11
|
+
...(artifact.metadata || {}),
|
|
12
|
+
...artifactUpdate.metadata,
|
|
13
|
+
};
|
|
14
|
+
artifact.description = artifactUpdate.description;
|
|
15
|
+
artifact.name = artifactUpdate.name;
|
|
16
|
+
artifact.parts.push(...artifactUpdate.parts);
|
|
17
|
+
return artifact;
|
|
27
18
|
}
|
|
28
|
-
export function
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
if (!replaced) {
|
|
36
|
-
newArtifacts.push({ ...artifactUpdate });
|
|
19
|
+
export function upsertArtifact(artifacts, update) {
|
|
20
|
+
const updateId = update.artifact.artifactId;
|
|
21
|
+
const index = artifacts.findIndex((a) => a.artifactId === updateId);
|
|
22
|
+
if (index === -1) {
|
|
23
|
+
artifacts.push({ ...update.artifact });
|
|
24
|
+
return artifacts;
|
|
37
25
|
}
|
|
38
|
-
|
|
26
|
+
artifacts[index] = updateArtifact(artifacts[index], update);
|
|
27
|
+
return artifacts;
|
|
39
28
|
}
|
|
@@ -16,7 +16,13 @@ export const cancelTask = async ({ id: taskId }, context) => {
|
|
|
16
16
|
if (FINAL_STATES.includes(task.status.state)) {
|
|
17
17
|
throw TASK_NOT_CANCELABLE("Task is in a final state: " + task.status.state);
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* By triggering onCancel, we're guaranteed that:
|
|
21
|
+
* - No further updates will be processed other than errors
|
|
22
|
+
* - The task will be cancelled
|
|
23
|
+
* - The task will be completed
|
|
24
|
+
* - The cancellations will be cleaned up
|
|
25
|
+
*/
|
|
20
26
|
const cancelledTask = {
|
|
21
27
|
...task,
|
|
22
28
|
status: {
|
|
@@ -24,10 +30,6 @@ export const cancelTask = async ({ id: taskId }, context) => {
|
|
|
24
30
|
state: A2A.TaskState.canceled,
|
|
25
31
|
},
|
|
26
32
|
};
|
|
27
|
-
context.publisher?.on("complete", async () => {
|
|
28
|
-
await service.cancellations.delete(taskId);
|
|
29
|
-
await service.contexts.delete(context.contextId);
|
|
30
|
-
});
|
|
31
33
|
await context.publisher.onCancel(cancelledTask);
|
|
32
34
|
return cancelledTask;
|
|
33
35
|
};
|
|
@@ -3,9 +3,17 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { A2A } from "../../../types/index.js";
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const subscribeToTask: A2A.RequestHandler["resubscribe"];
|
|
7
|
+
export type SubscribeToTaskHandler = typeof subscribeToTask;
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use SubscribeToTaskHandler instead
|
|
10
|
+
*/
|
|
11
|
+
export declare const resubscribe: (input: A2A.TaskIdParams, context?: A2A.Context, options?: A2A.ServiceOptions) => AsyncGenerator<A2A.Update>;
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use SubscribeToTaskHandler instead
|
|
14
|
+
*/
|
|
7
15
|
export type TaskResubscribeHandler = typeof resubscribe;
|
|
8
16
|
/**
|
|
9
|
-
* @deprecated Use
|
|
17
|
+
* @deprecated Use SubscribeToTaskHandler instead
|
|
10
18
|
*/
|
|
11
19
|
export type ResubscribeTaskMethod = TaskResubscribeHandler;
|
|
@@ -5,22 +5,22 @@
|
|
|
5
5
|
import { A2A } from "../../../types/index.js";
|
|
6
6
|
import { FINAL_STATES, INTERNAL_ERROR, TASK_NOT_FOUND } from "../../../utils/index.js";
|
|
7
7
|
const flush = (task, stream) => {
|
|
8
|
-
if (task.artifacts
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
if (!task.artifacts || task.artifacts.length === 0)
|
|
9
|
+
return;
|
|
10
|
+
for (const artifact of task.artifacts) {
|
|
11
|
+
const artifactUpdate = {
|
|
12
|
+
kind: A2A.Kind["artifact-update"],
|
|
13
|
+
taskId: task.id,
|
|
14
|
+
contextId: task.contextId,
|
|
15
|
+
artifact,
|
|
16
|
+
lastChunk: task.artifacts.length === 1,
|
|
17
|
+
metadata: task.metadata,
|
|
18
|
+
};
|
|
19
|
+
stream.updates.push(artifactUpdate);
|
|
20
|
+
task.artifacts.shift();
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
export const
|
|
23
|
+
export const subscribeToTask = async function* ({ id: taskId }, context) {
|
|
24
24
|
if (!context) {
|
|
25
25
|
throw INTERNAL_ERROR({ error: { message: "Context is required" } });
|
|
26
26
|
}
|
|
@@ -33,9 +33,7 @@ export const resubscribe = async function* ({ id: taskId }, context) {
|
|
|
33
33
|
contextId: context.contextId,
|
|
34
34
|
context,
|
|
35
35
|
}));
|
|
36
|
-
//
|
|
37
|
-
// then we dont care about the upsert in onStart
|
|
38
|
-
// so we can just push the update and continue
|
|
36
|
+
// onStart no longer inserts a new task, so we can safely push the update and continue
|
|
39
37
|
context.publisher.on("start", async (_, task) => {
|
|
40
38
|
stream.updates.push({
|
|
41
39
|
kind: "status-update",
|
|
@@ -46,7 +44,8 @@ export const resubscribe = async function* ({ id: taskId }, context) {
|
|
|
46
44
|
metadata: task.metadata,
|
|
47
45
|
});
|
|
48
46
|
if (FINAL_STATES.includes(task.status.state)) {
|
|
49
|
-
|
|
47
|
+
/* We create a new task object to avoid mutating the original task */
|
|
48
|
+
flush({ ...task }, stream);
|
|
50
49
|
await stream.kill();
|
|
51
50
|
}
|
|
52
51
|
});
|
|
@@ -54,3 +53,7 @@ export const resubscribe = async function* ({ id: taskId }, context) {
|
|
|
54
53
|
service: service,
|
|
55
54
|
});
|
|
56
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* @deprecated Use SubscribeToTaskHandler instead
|
|
58
|
+
*/
|
|
59
|
+
export const resubscribe = subscribeToTask;
|
|
@@ -8,15 +8,10 @@ export const sendMessage = async ({ configuration }, context) => {
|
|
|
8
8
|
if (!context) {
|
|
9
9
|
throw INTERNAL_ERROR({ error: { message: "Context is required" } });
|
|
10
10
|
}
|
|
11
|
-
context.publisher.on("complete", () => {
|
|
12
|
-
context.service.contexts.delete(context.contextId);
|
|
13
|
-
});
|
|
14
|
-
context.publisher.on("error", () => {
|
|
15
|
-
context.publisher.onComplete();
|
|
16
|
-
});
|
|
17
11
|
const service = context.service;
|
|
12
|
+
let task;
|
|
18
13
|
if (configuration?.blocking === false) {
|
|
19
|
-
|
|
14
|
+
task = await Promise.race([
|
|
20
15
|
service.execute({ engine: service.engine, context }).then(async () => {
|
|
21
16
|
return await context.getTask();
|
|
22
17
|
}),
|
|
@@ -26,10 +21,11 @@ export const sendMessage = async ({ configuration }, context) => {
|
|
|
26
21
|
});
|
|
27
22
|
}),
|
|
28
23
|
]);
|
|
29
|
-
return result;
|
|
30
24
|
}
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
else {
|
|
26
|
+
await service.execute({ engine: service.engine, context });
|
|
27
|
+
task = await context.getTask();
|
|
28
|
+
}
|
|
33
29
|
task.history = getLatestHistory(task, configuration?.historyLength);
|
|
34
30
|
return task;
|
|
35
31
|
};
|
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { A2A } from "../../../types/index.js";
|
|
6
|
-
export declare const
|
|
7
|
-
export type
|
|
6
|
+
export declare const sendMessageStream: A2A.RequestHandler["streamMessage"];
|
|
7
|
+
export type SendMessageStreamHandler = typeof sendMessageStream;
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use sendMessageStream instead
|
|
10
|
+
*/
|
|
11
|
+
export declare const streamMessage: (message: A2A.MessageSendParams, context?: A2A.Context, options?: A2A.ServiceOptions) => AsyncGenerator<A2A.Update>;
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use SendMessageStreamHandler instead
|
|
14
|
+
*/
|
|
15
|
+
export type StreamMessageHandler = SendMessageStreamHandler;
|
|
8
16
|
/**
|
|
9
17
|
* @deprecated Use StreamMessageHandler instead
|
|
10
18
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { INTERNAL_ERROR } from "../../../utils/index.js";
|
|
6
|
-
export const
|
|
6
|
+
export const sendMessageStream = async function* (_, context) {
|
|
7
7
|
if (!context) {
|
|
8
8
|
throw INTERNAL_ERROR({ error: { message: "Context is required" } });
|
|
9
9
|
}
|
|
@@ -17,3 +17,7 @@ export const streamMessage = async function* (_, context) {
|
|
|
17
17
|
});
|
|
18
18
|
yield* stream.run({ service });
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Use sendMessageStream instead
|
|
22
|
+
*/
|
|
23
|
+
export const streamMessage = sendMessageStream;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Copyright 2025 The Artinet Project
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { getCurrentTimestamp,
|
|
6
|
-
import {
|
|
5
|
+
import { getCurrentTimestamp, formatJson } from "../../../utils/common/utils.js";
|
|
6
|
+
import { validateSchema } from "../../../utils/common/schema-validation.js";
|
|
7
|
+
import { upsertArtifact } from "./artifact.js";
|
|
7
8
|
import { A2A } from "../../../types/index.js";
|
|
8
9
|
import { logger } from "../../../config/index.js";
|
|
9
10
|
const isMessageInHistory = (task, message) => {
|
|
@@ -17,9 +18,13 @@ const updateHistory = (task, updateMessage) => {
|
|
|
17
18
|
export const handleMessageUpdate = async ({ task, update, }) => {
|
|
18
19
|
const validated = await validateSchema(A2A.MessageSchema, update);
|
|
19
20
|
if (validated.taskId && task.id !== validated.taskId) {
|
|
20
|
-
throw new Error(`updateMessage: Invalid task id: ${validated.taskId}
|
|
21
|
-
cause:
|
|
22
|
-
|
|
21
|
+
throw new Error(`updateMessage: Invalid task id: ${validated.taskId} ${formatJson({
|
|
22
|
+
cause: {
|
|
23
|
+
validated,
|
|
24
|
+
actual: task.id,
|
|
25
|
+
task,
|
|
26
|
+
},
|
|
27
|
+
})}`);
|
|
23
28
|
}
|
|
24
29
|
updateHistory(task, validated);
|
|
25
30
|
return task;
|
|
@@ -59,7 +64,7 @@ export const handleArtifactUpdate = async ({ task, update }) => {
|
|
|
59
64
|
else {
|
|
60
65
|
validated.taskId = task.id;
|
|
61
66
|
}
|
|
62
|
-
task.artifacts =
|
|
67
|
+
task.artifacts = upsertArtifact(task.artifacts ?? [], validated);
|
|
63
68
|
return task;
|
|
64
69
|
};
|
|
65
70
|
// The onus is now on the caller to handle errors when processing updates
|
|
@@ -8,4 +8,8 @@ import { A2A } from "../../../types/index.js";
|
|
|
8
8
|
* @param input - The input event.
|
|
9
9
|
* @returns The content of the input event.
|
|
10
10
|
*/
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function extractTextContent(input: A2A.Update): string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use extractTextContent instead.
|
|
14
|
+
*/
|
|
15
|
+
export declare const getContent: typeof extractTextContent;
|
|
@@ -8,7 +8,7 @@ import { getParts } from "./part.js";
|
|
|
8
8
|
* @param input - The input event.
|
|
9
9
|
* @returns The content of the input event.
|
|
10
10
|
*/
|
|
11
|
-
export function
|
|
11
|
+
export function extractTextContent(input) {
|
|
12
12
|
const parts = getParts(input?.parts ??
|
|
13
13
|
input?.status?.message?.parts ??
|
|
14
14
|
input?.status?.message?.parts ??
|
|
@@ -20,3 +20,7 @@ export function getContent(input) {
|
|
|
20
20
|
parts.data.map((data) => JSON.stringify(data)).join("\n") ??
|
|
21
21
|
undefined);
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated Use extractTextContent instead.
|
|
25
|
+
*/
|
|
26
|
+
export const getContent = extractTextContent;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./part.js";
|
|
2
2
|
export * from "./content.js";
|
|
3
|
-
export
|
|
4
|
-
export
|
|
3
|
+
export { AgentCardBuilder } from "../../../create/agentcard-builder.js";
|
|
4
|
+
export { MessageBuilder, MessageSendConfigurationBuilder, } from "../../../create/message-builder.js";
|
|
5
5
|
export * from "./history.js";
|
|
6
6
|
export * from "./references.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./part.js";
|
|
2
2
|
export * from "./content.js";
|
|
3
|
-
export
|
|
4
|
-
export
|
|
3
|
+
export { AgentCardBuilder } from "../../../create/agentcard-builder.js";
|
|
4
|
+
export { MessageBuilder, MessageSendConfigurationBuilder, } from "../../../create/message-builder.js";
|
|
5
5
|
export * from "./history.js";
|
|
6
6
|
export * from "./references.js";
|