@microsoft/teams.a2a 2.0.0-preview.3
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 +180 -0
- package/dist/chat-prompt/plugin.d.ts +24 -0
- package/dist/chat-prompt/plugin.js +153 -0
- package/dist/chat-prompt/types.d.ts +60 -0
- package/dist/chat-prompt/types.js +3 -0
- package/dist/client/agent-client.d.ts +58 -0
- package/dist/client/agent-client.js +177 -0
- package/dist/client/agent-manager.d.ts +57 -0
- package/dist/client/agent-manager.js +136 -0
- package/dist/client/agent-task-store.d.ts +25 -0
- package/dist/client/agent-task-store.js +47 -0
- package/dist/common/schema.d.ts +728 -0
- package/dist/common/schema.js +26 -0
- package/dist/common/type-utils.d.ts +11 -0
- package/dist/common/type-utils.js +3 -0
- package/dist/common/uuid.d.ts +1 -0
- package/dist/common/uuid.js +12 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +50 -0
- package/dist/server/middleware/isTaskRequest.d.ts +2 -0
- package/dist/server/middleware/isTaskRequest.js +32 -0
- package/dist/server/plugin.d.ts +49 -0
- package/dist/server/plugin.js +130 -0
- package/dist/server/plugin.on-get-request.d.ts +3 -0
- package/dist/server/plugin.on-get-request.js +17 -0
- package/dist/server/plugin.on-send-request.d.ts +9 -0
- package/dist/server/plugin.on-send-request.js +107 -0
- package/dist/server/serverUtils.d.ts +13 -0
- package/dist/server/serverUtils.js +65 -0
- package/dist/server/tasks/task-manager.d.ts +22 -0
- package/dist/server/tasks/task-manager.js +205 -0
- package/dist/server/tasks/task-store.d.ts +8 -0
- package/dist/server/tasks/task-store.js +18 -0
- package/dist/server/tasks/task-utilities.d.ts +27 -0
- package/dist/server/tasks/task-utilities.js +139 -0
- package/dist/server/tasks/task-utils.d.ts +22 -0
- package/dist/server/tasks/task-utils.js +38 -0
- package/dist/server/types/a2a-error.d.ts +23 -0
- package/dist/server/types/a2a-error.js +95 -0
- package/dist/server/types/a2a-types.d.ts +56 -0
- package/dist/server/types/a2a-types.js +3 -0
- package/dist/server/types/event-types.d.ts +24 -0
- package/dist/server/types/event-types.js +3 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Teams: a2a
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://www.npmjs.com/package/@microsoft/teams.a2a" target="_blank">
|
|
5
|
+
<img src="https://img.shields.io/npm/v/@microsoft/teams.a2a" />
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/@microsoft/teams.a2a?activeTab=code" target="_blank">
|
|
8
|
+
<img src="https://img.shields.io/bundlephobia/min/@microsoft/teams.a2a" />
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/@microsoft/teams.a2a?activeTab=dependencies" target="_blank">
|
|
11
|
+
<img src="https://img.shields.io/librariesio/release/npm/@microsoft/teams.a2a" />
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/@microsoft/teams.a2a" target="_blank">
|
|
14
|
+
<img src="https://img.shields.io/npm/dw/@microsoft/teams.a2a" />
|
|
15
|
+
</a>
|
|
16
|
+
<a href="https://microsoft.github.io/teams.ts" target="_blank">
|
|
17
|
+
<img src="https://img.shields.io/badge/📖 docs-open-blue" />
|
|
18
|
+
</a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
This is a plugin that enables your Teams agent to be used as an A2A agent.
|
|
22
|
+
|
|
23
|
+
> [!NOTE]
|
|
24
|
+
> The A2A protocol is still early in development and hence this package is fairly experimental.
|
|
25
|
+
|
|
26
|
+
- [What is A2A?](https://google.github.io/A2A)
|
|
27
|
+
|
|
28
|
+
## Server
|
|
29
|
+
|
|
30
|
+
Teams AI Library allows your applications to easily be accessible via Teams. However, using this plugin, you can also enable your agent to be used as an A2A agent so that it can be used by other A2A clients.
|
|
31
|
+
|
|
32
|
+
### Configuration
|
|
33
|
+
|
|
34
|
+
Configuring the App to use the A2APlugin simply requires the `AgentCard`.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { schema, A2APlugin } from "@microsoft/teams.a2a";
|
|
38
|
+
import { App } from "@microsoft/teams.apps";
|
|
39
|
+
|
|
40
|
+
declare const myAgentCard: AgentCard;
|
|
41
|
+
|
|
42
|
+
const app = new App({
|
|
43
|
+
plugins: [
|
|
44
|
+
new A2APlugin({
|
|
45
|
+
agentCard: myAgentCard,
|
|
46
|
+
}),
|
|
47
|
+
],
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
With this simple configuration, the A2APlugin will listen for A2A requests on the `/a2a` path and return the agent card when requested.
|
|
52
|
+
|
|
53
|
+
### Agent Card
|
|
54
|
+
|
|
55
|
+
The plugin automatically exposes the agent card at the path `/.well-known/agent.json`.
|
|
56
|
+
|
|
57
|
+
```mermaid
|
|
58
|
+
sequenceDiagram
|
|
59
|
+
participant A2A Client
|
|
60
|
+
participant App
|
|
61
|
+
participant A2APlugin
|
|
62
|
+
A2A Client->>App: /.well-known/agent.json
|
|
63
|
+
App->>A2APlugin: Call A2APlugin
|
|
64
|
+
A2APlugin->>A2A Client: Return agent card
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### A2A Requests
|
|
68
|
+
|
|
69
|
+
```mermaid
|
|
70
|
+
sequenceDiagram
|
|
71
|
+
participant A2A Client
|
|
72
|
+
participant App
|
|
73
|
+
participant A2APlugin
|
|
74
|
+
participant YourEventHandler
|
|
75
|
+
A2A Client->>App: /task/send
|
|
76
|
+
App->>A2APlugin: Call A2APlugin
|
|
77
|
+
A2APlugin->>YourEventHandler: Call your event handler a2a:message
|
|
78
|
+
YourEventHandler->>A2APlugin: Call respond
|
|
79
|
+
A2APlugin->>A2A Client: Return response
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Handling A2A requests is similar to handling app-requests. Simply add an event handler for the `a2a:message` event. You may `accumulateArtifacts` to iteratively accumulate artifacts for the task, or simply `respond` with the final result.
|
|
83
|
+
|
|
84
|
+
> [!NOTE]
|
|
85
|
+
> You must have only a single handler that calls `respond`. And you **must** call `respond` as the last step in your handler. This is because the `respond` function resolves the open request to the caller.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
app.event(
|
|
89
|
+
"a2a:message",
|
|
90
|
+
async ({ taskContext, respond, accumulateArtifacts }) => {
|
|
91
|
+
// The taskContext contains details about the task request
|
|
92
|
+
const result = await myEventHandler(taskContext, accumulateArtifacts);
|
|
93
|
+
await respond(result);
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Client
|
|
99
|
+
|
|
100
|
+
The A2A client is able to call different A2A servers. You are able to use the `AgentManager` to call different A2A Servers.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { AgentManager } from "@microsoft/teams.a2a";
|
|
104
|
+
|
|
105
|
+
const agentManager = new AgentManager();
|
|
106
|
+
|
|
107
|
+
agentManager.use("my-agent", "https://my-agent.com/a2a");
|
|
108
|
+
await agentManager.sendTask("my-agent", {
|
|
109
|
+
id: continueTaskId || generateRequestId().toString(),
|
|
110
|
+
message: {
|
|
111
|
+
role: 'user',
|
|
112
|
+
parts: [{ type: 'text' as const, text: message }],
|
|
113
|
+
},
|
|
114
|
+
{},
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
If you are using the `A2APlugin` described above, you can use the `clientManger` property in that plugin object to get an instance of the `AgentManager` and use it to send tasks proactively to different A2A servers.
|
|
119
|
+
|
|
120
|
+
### Chat Prompt
|
|
121
|
+
|
|
122
|
+
A2A is most effective when used with an LLM. The `A2AClientPlugin` can be used to add a plugin to your chat prompt that will allow you to automatically include A2A agents as a possible source of interaction. The interaction can be outlined as below:
|
|
123
|
+
|
|
124
|
+
```mermaid
|
|
125
|
+
sequenceDiagram
|
|
126
|
+
participant User
|
|
127
|
+
participant ChatPrompt
|
|
128
|
+
participant A2AClientPlugin
|
|
129
|
+
participant AgentManager
|
|
130
|
+
participant AgentClient
|
|
131
|
+
participant LLM
|
|
132
|
+
participant TargetAgent
|
|
133
|
+
|
|
134
|
+
alt config
|
|
135
|
+
User->>ChatPrompt: "use" with A2A server details
|
|
136
|
+
ChatPrompt->>A2AClientPlugin: configure usable a2a server
|
|
137
|
+
A2AClientPlugin->>AgentManager: register new potential client
|
|
138
|
+
end
|
|
139
|
+
alt send
|
|
140
|
+
User->>ChatPrompt: Send initial message
|
|
141
|
+
ChatPrompt->>A2AClientPlugin: configure system prompt
|
|
142
|
+
A2AClientPlugin->>AgentManager: get agent cards
|
|
143
|
+
AgentManager->>AgentClient: for each get agent card
|
|
144
|
+
AgentClient-->>AgentManager: agent card
|
|
145
|
+
AgentManager-->>A2AClientPlugin: all agent cards
|
|
146
|
+
A2AClientPlugin-->>ChatPrompt: updated system prompt
|
|
147
|
+
ChatPrompt->>A2AClientPlugin: configure tool-calls (onBuildFunctions)
|
|
148
|
+
A2AClientPlugin-->>ChatPrompt: Configured tool calls
|
|
149
|
+
ChatPrompt->>LLM: send-message
|
|
150
|
+
LLM-->>ChatPrompt: Call A2A TargetAgent
|
|
151
|
+
ChatPrompt->>A2AClientPlugin: Handler for calling A2A TargetAgent
|
|
152
|
+
A2AClientPlugin->>AgentManager: Call TargetAgent with message
|
|
153
|
+
AgentManager->>AgentClient: Call TargetAgent with message
|
|
154
|
+
TargetAgent-->>AgentClient: Return task (e.g., completed, input-required)
|
|
155
|
+
AgentClient->>AgentManager: Result task
|
|
156
|
+
AgentManager->>A2AClientPlugin: Result task
|
|
157
|
+
A2AClientPlugin->>ChatPrompt: Result task
|
|
158
|
+
ChatPrompt-->>User: Respond with final result or follow-up
|
|
159
|
+
end
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Usage:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { A2APlugin } from "@microsoft/teams.a2a";
|
|
166
|
+
import { ChatPrompt } from "@microsoft/teams.ai";
|
|
167
|
+
|
|
168
|
+
const plugin = new A2APlugin();
|
|
169
|
+
|
|
170
|
+
const chatPrompt = new ChatPrompt({
|
|
171
|
+
plugins: [plugin],
|
|
172
|
+
}).usePlugin("a2a", {
|
|
173
|
+
key: "my-agent",
|
|
174
|
+
url: "https://my-agent.com/a2a",
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const result = await chatPrompt.sendMessage("Hello, world!");
|
|
178
|
+
|
|
179
|
+
console.log(result);
|
|
180
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Function as ChatFunction, ChatPromptPlugin } from '@microsoft/teams.ai';
|
|
2
|
+
import { AgentManager } from '../client/agent-manager';
|
|
3
|
+
import * as schema from '../common/schema';
|
|
4
|
+
import { A2APluginOptions, A2APluginUseParams, BuildFunctionMetadata, BuildPrompt, BuildTaskSendParams } from './types';
|
|
5
|
+
export declare class A2AClientPlugin implements ChatPromptPlugin<'a2a', A2APluginUseParams> {
|
|
6
|
+
readonly name = "a2a";
|
|
7
|
+
protected _manager: AgentManager;
|
|
8
|
+
protected buildFunctionMetadata?: BuildFunctionMetadata;
|
|
9
|
+
protected buildPrompt?: BuildPrompt;
|
|
10
|
+
protected buildTaskSendParams?: BuildTaskSendParams;
|
|
11
|
+
protected _agentConfig: Map<string, Partial<A2APluginUseParams>>;
|
|
12
|
+
constructor(options?: A2APluginOptions);
|
|
13
|
+
onUsePlugin(args: A2APluginUseParams): void;
|
|
14
|
+
onBuildFunctions(functions: ChatFunction[]): Promise<ChatFunction[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Modify the system prompt before it is sent to the model.
|
|
17
|
+
* If the user supplies a buildPrompt function, it is used. Otherwise, a default is built.
|
|
18
|
+
*/
|
|
19
|
+
onBuildPrompt(systemPrompt: string | undefined): Promise<string | undefined>;
|
|
20
|
+
private _defaultFunctionMetadata;
|
|
21
|
+
private _defaultBuildPrompt;
|
|
22
|
+
private _defaultBuildTaskSendParams;
|
|
23
|
+
}
|
|
24
|
+
export declare const buildTaskSendParams: (message: string, metadata?: Record<string, any>, continueTaskId?: string | null) => schema.TaskSendParams;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildTaskSendParams = exports.A2AClientPlugin = void 0;
|
|
7
|
+
const camelcase_1 = __importDefault(require("camelcase"));
|
|
8
|
+
const agent_manager_1 = require("../client/agent-manager");
|
|
9
|
+
const uuid_1 = require("../common/uuid");
|
|
10
|
+
class A2AClientPlugin {
|
|
11
|
+
name = 'a2a';
|
|
12
|
+
_manager;
|
|
13
|
+
buildFunctionMetadata;
|
|
14
|
+
buildPrompt;
|
|
15
|
+
buildTaskSendParams;
|
|
16
|
+
_agentConfig = new Map();
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this._manager = options.manager instanceof agent_manager_1.AgentManager ? options.manager : new agent_manager_1.AgentManager(options.manager);
|
|
19
|
+
this.buildFunctionMetadata = options.buildFunctionMetadata;
|
|
20
|
+
this.buildPrompt = options.buildPrompt;
|
|
21
|
+
this.buildTaskSendParams = options.buildTaskSendParams;
|
|
22
|
+
}
|
|
23
|
+
onUsePlugin(args) {
|
|
24
|
+
this._manager.use(args.key, args.url, args.agentCard);
|
|
25
|
+
// Store per-agent config (excluding agentCard and url)
|
|
26
|
+
const { key, url, agentCard, ...rest } = args;
|
|
27
|
+
this._agentConfig.set(key, rest);
|
|
28
|
+
}
|
|
29
|
+
async onBuildFunctions(functions) {
|
|
30
|
+
const cards = await this._manager.getAgentCards();
|
|
31
|
+
const allFunctions = [];
|
|
32
|
+
for (const cardWithMeta of cards) {
|
|
33
|
+
if (!cardWithMeta) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const { key, card } = cardWithMeta;
|
|
37
|
+
const agentConfig = this._agentConfig.get(key) || {};
|
|
38
|
+
const buildFunctionMetadata = agentConfig.buildFunctionMetadata ||
|
|
39
|
+
this.buildFunctionMetadata ||
|
|
40
|
+
this._defaultFunctionMetadata;
|
|
41
|
+
const buildTaskSendParams = agentConfig.buildTaskSendParams ||
|
|
42
|
+
this.buildTaskSendParams ||
|
|
43
|
+
this._defaultBuildTaskSendParams;
|
|
44
|
+
const { name, description } = buildFunctionMetadata(card);
|
|
45
|
+
allFunctions.push({
|
|
46
|
+
name,
|
|
47
|
+
description,
|
|
48
|
+
parameters: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
message: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'Message to send to the agent',
|
|
54
|
+
},
|
|
55
|
+
continueTaskId: {
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: 'If provided, continue an existing task with this ID (string). Otherwise send null or NONE to indicate a new task.',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
required: ['message'],
|
|
61
|
+
},
|
|
62
|
+
handler: async (args) => {
|
|
63
|
+
const agentMessage = args.message;
|
|
64
|
+
if (!agentMessage) {
|
|
65
|
+
throw new Error(`An input message is required to call Agent ${name}!`);
|
|
66
|
+
}
|
|
67
|
+
const continueTaskId = args.continueTaskId != null
|
|
68
|
+
? args.continueTaskId.toLowerCase() === 'none'
|
|
69
|
+
? null
|
|
70
|
+
: args.continueTaskId || null
|
|
71
|
+
: null;
|
|
72
|
+
const sendParams = buildTaskSendParams(card, agentMessage, continueTaskId);
|
|
73
|
+
const result = await this._manager.sendTask(key, sendParams);
|
|
74
|
+
return result;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return functions.concat(allFunctions);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Modify the system prompt before it is sent to the model.
|
|
82
|
+
* If the user supplies a buildPrompt function, it is used. Otherwise, a default is built.
|
|
83
|
+
*/
|
|
84
|
+
async onBuildPrompt(systemPrompt) {
|
|
85
|
+
const cardsWithMeta = await this._manager.getAgentCards();
|
|
86
|
+
// Lookup latest tasks for all agents first
|
|
87
|
+
const agentsWithLatestTask = [];
|
|
88
|
+
for (const cardWithMeta of cardsWithMeta) {
|
|
89
|
+
if (!cardWithMeta) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const { key, card } = cardWithMeta;
|
|
93
|
+
const latestTask = await this._manager.getLatestTask(key);
|
|
94
|
+
agentsWithLatestTask.push({ card, latestTask });
|
|
95
|
+
}
|
|
96
|
+
// If the user supplied a buildPrompt, use it
|
|
97
|
+
if (this.buildPrompt) {
|
|
98
|
+
return this.buildPrompt(systemPrompt, agentsWithLatestTask);
|
|
99
|
+
}
|
|
100
|
+
const prompt = (systemPrompt || '') +
|
|
101
|
+
'\n' +
|
|
102
|
+
this._defaultBuildPrompt(agentsWithLatestTask);
|
|
103
|
+
return prompt;
|
|
104
|
+
}
|
|
105
|
+
_defaultFunctionMetadata(card) {
|
|
106
|
+
const name = `message${(0, camelcase_1.default)(card.name, { pascalCase: true })}`;
|
|
107
|
+
const description = card.description || `Interact with agent at ${card.url}`;
|
|
108
|
+
return { name, description };
|
|
109
|
+
}
|
|
110
|
+
_defaultBuildPrompt(agentDetails) {
|
|
111
|
+
let details = 'Here are details about available agents that you can message. Determine the best phrasing to use when you are attempting to message them.';
|
|
112
|
+
for (const { card, latestTask } of agentDetails) {
|
|
113
|
+
details += '<Agent Details>\n';
|
|
114
|
+
details += `<Name>\n${card.name || card.url}\n</Name>\n`;
|
|
115
|
+
if (card.description) {
|
|
116
|
+
details += `<Description>\n${card.description}\n</Description>\n`;
|
|
117
|
+
}
|
|
118
|
+
for (const skill of card.skills || []) {
|
|
119
|
+
details += `<SKILL name=${skill.name} description=${skill.description} />\n`;
|
|
120
|
+
if (skill.examples) {
|
|
121
|
+
details += `<EXAMPLES>\n${skill.examples.join('\n')}\n</EXAMPLES>\n`;
|
|
122
|
+
}
|
|
123
|
+
details += '</SKILL>\n';
|
|
124
|
+
}
|
|
125
|
+
if (latestTask) {
|
|
126
|
+
const lastMessage = latestTask.history && latestTask.history.length > 0
|
|
127
|
+
? latestTask.history[latestTask.history.length - 1].parts
|
|
128
|
+
.map((p) => p.type === 'text' ? p.text : '[non-text]')
|
|
129
|
+
.join(' ')
|
|
130
|
+
: '';
|
|
131
|
+
details += `<PREVIOUS_TASK_DETAILS taskId=${latestTask.task.id} state=${latestTask.task.status.state} lastMessage=${lastMessage}\n</PREVIOUS_TASK_DETAILS>`;
|
|
132
|
+
}
|
|
133
|
+
details += '</Agent Details>\n';
|
|
134
|
+
}
|
|
135
|
+
return details;
|
|
136
|
+
}
|
|
137
|
+
_defaultBuildTaskSendParams(_card, message, continueTaskId, metadata) {
|
|
138
|
+
return (0, exports.buildTaskSendParams)(message, metadata, continueTaskId);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.A2AClientPlugin = A2AClientPlugin;
|
|
142
|
+
const buildTaskSendParams = (message, metadata, continueTaskId) => {
|
|
143
|
+
return {
|
|
144
|
+
id: continueTaskId || (0, uuid_1.generateRequestId)().toString(),
|
|
145
|
+
message: {
|
|
146
|
+
role: 'user',
|
|
147
|
+
parts: [{ type: 'text', text: message }],
|
|
148
|
+
},
|
|
149
|
+
metadata,
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
exports.buildTaskSendParams = buildTaskSendParams;
|
|
153
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NoYXQtcHJvbXB0L3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwwREFBa0M7QUFPbEMsMkRBQTZFO0FBRTdFLHlDQUFtRDtBQVduRCxNQUFhLGVBQWU7SUFFakIsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUNaLFFBQVEsQ0FBZTtJQUN2QixxQkFBcUIsQ0FBeUI7SUFDOUMsV0FBVyxDQUFlO0lBQzFCLG1CQUFtQixDQUF1QjtJQUMxQyxZQUFZLEdBQTZDLElBQUksR0FBRyxFQUFFLENBQUM7SUFFN0UsWUFBWSxVQUE0QixFQUFFO1FBQ3hDLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLE9BQU8sWUFBWSw0QkFBWSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLDRCQUFZLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlHLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUM7UUFDM0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUM7SUFDekQsQ0FBQztJQUVELFdBQVcsQ0FBQyxJQUF3QjtRQUNsQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RELHVEQUF1RDtRQUN2RCxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lB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
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AgentManager, AgentManagerOptions } from '../client/agent-manager';
|
|
2
|
+
import * as schema from '../common/schema';
|
|
3
|
+
import { TaskAndHistory } from '../server/types/a2a-types';
|
|
4
|
+
/**
|
|
5
|
+
* Parameters for registering an agent with the A2A plugin.
|
|
6
|
+
* usage: new ChatPrompt(..., [new A2APlugin(...)]).use(A2APluginParams)
|
|
7
|
+
*/
|
|
8
|
+
export type A2APluginUseParams = {
|
|
9
|
+
/**
|
|
10
|
+
* Unique key for this agent (used for config and lookup)
|
|
11
|
+
*/
|
|
12
|
+
key: string;
|
|
13
|
+
/**
|
|
14
|
+
* The agent's base URL
|
|
15
|
+
*/
|
|
16
|
+
url: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional agent card for the agent
|
|
19
|
+
*/
|
|
20
|
+
agentCard?: schema.AgentCard;
|
|
21
|
+
/**
|
|
22
|
+
* Optional function to customize function metadata for this agent
|
|
23
|
+
*/
|
|
24
|
+
buildFunctionMetadata?: BuildFunctionMetadata;
|
|
25
|
+
/**
|
|
26
|
+
* Optional function to customize TaskSendParams for this agent
|
|
27
|
+
*/
|
|
28
|
+
buildTaskSendParams?: BuildTaskSendParams;
|
|
29
|
+
};
|
|
30
|
+
export type AgentPromptParams = {
|
|
31
|
+
card: schema.AgentCard;
|
|
32
|
+
latestTask?: TaskAndHistory | null;
|
|
33
|
+
};
|
|
34
|
+
export type BuildFunctionMetadata = (card: schema.AgentCard) => {
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
};
|
|
38
|
+
export type BuildTaskSendParams = (card: schema.AgentCard, input: string, continueTaskId?: string | null, metadata?: Record<string, any>) => schema.TaskSendParams;
|
|
39
|
+
export type BuildPrompt = (incomingSystemPrompt: string | undefined, agentDetails: AgentPromptParams[]) => string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Options for constructing an A2APlugin.
|
|
42
|
+
*/
|
|
43
|
+
export type A2APluginOptions = {
|
|
44
|
+
/**
|
|
45
|
+
* Optional A2AAgentManager instance to use for agent management.
|
|
46
|
+
*/
|
|
47
|
+
manager?: AgentManager | AgentManagerOptions;
|
|
48
|
+
/**
|
|
49
|
+
* Optional function to customize the function name and description for each agent card.
|
|
50
|
+
*/
|
|
51
|
+
buildFunctionMetadata?: BuildFunctionMetadata;
|
|
52
|
+
/**
|
|
53
|
+
* Optional function to customize the prompt given all agent cards.
|
|
54
|
+
*/
|
|
55
|
+
buildPrompt?: BuildPrompt;
|
|
56
|
+
/**
|
|
57
|
+
* Optional function to customize TaskSendParams given the input and context.
|
|
58
|
+
*/
|
|
59
|
+
buildTaskSendParams?: BuildTaskSendParams;
|
|
60
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2hhdC1wcm9tcHQvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ILogger } from '@microsoft/teams.common';
|
|
2
|
+
import { type AgentCard, type Task, type TaskSendParams } from '../common/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Options for constructing an A2AAgentClient.
|
|
5
|
+
*/
|
|
6
|
+
export type A2AAgentClientOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* The base URL of the A2A agent endpoint. The client will fetch the agent card from this URL if agentCard is not provided.
|
|
9
|
+
*/
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
/**
|
|
12
|
+
* The agent card object. If provided, the client will use this directly and will not fetch it from the network.
|
|
13
|
+
*/
|
|
14
|
+
agentCard?: AgentCard;
|
|
15
|
+
/**
|
|
16
|
+
* Optional custom fetch implementation (e.g., for Node.js environments without global fetch). Defaults to global fetch.
|
|
17
|
+
*/
|
|
18
|
+
fetchImpl?: typeof fetch;
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
logger?: ILogger;
|
|
23
|
+
};
|
|
24
|
+
export declare class AgentCardNotFoundError extends Error {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A2AAgentClient can be constructed with either a baseUrl (to fetch the agent card) or a direct AgentCard object.
|
|
29
|
+
* Optionally, a custom fetch implementation can be provided.
|
|
30
|
+
*/
|
|
31
|
+
export declare class AgentClient {
|
|
32
|
+
private _agentCard;
|
|
33
|
+
private _baseUrl;
|
|
34
|
+
get baseUrl(): string;
|
|
35
|
+
private _a2aUrl;
|
|
36
|
+
get a2aUrl(): string | null;
|
|
37
|
+
private _fetchImpl;
|
|
38
|
+
private _logger;
|
|
39
|
+
constructor(options: A2AAgentClientOptions);
|
|
40
|
+
/**
|
|
41
|
+
* Returns the agent card, fetching it if necessary.
|
|
42
|
+
*/
|
|
43
|
+
agentCard(): Promise<AgentCard>;
|
|
44
|
+
/**
|
|
45
|
+
* Sends a task request to the agent (non-streaming).
|
|
46
|
+
* @param params The parameters for the tasks/send method.
|
|
47
|
+
* @returns A promise resolving to the Task object or null.
|
|
48
|
+
*/
|
|
49
|
+
sendTask(params: TaskSendParams): Promise<Task | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Internal helper to make JSON-RPC HTTP requests.
|
|
52
|
+
*/
|
|
53
|
+
private _makeHttpRequest;
|
|
54
|
+
/**
|
|
55
|
+
* Handles standard JSON-RPC responses (non-streaming).
|
|
56
|
+
*/
|
|
57
|
+
private _handleJsonResponse;
|
|
58
|
+
}
|