@hanphone/dsh-a2a 0.1.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/LICENSE +21 -0
- package/README.md +196 -0
- package/README.zh.md +195 -0
- package/cordis.patch.yml +11 -0
- package/lib/client.js +166 -0
- package/lib/index.js +2073 -0
- package/lib/tsconfig.client.tsbuildinfo +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types/api.d.ts +41 -0
- package/lib/types/api.d.ts.map +1 -0
- package/lib/types/api.js +86 -0
- package/lib/types/api.js.map +1 -0
- package/lib/types/client/index.d.ts +35 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/index.js +155 -0
- package/lib/types/client/index.js.map +1 -0
- package/lib/types/commands.d.ts +10 -0
- package/lib/types/commands.d.ts.map +1 -0
- package/lib/types/commands.js +93 -0
- package/lib/types/commands.js.map +1 -0
- package/lib/types/events.d.ts +74 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +10 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/index.d.ts +54 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +296 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/jsonrpc.d.ts +20 -0
- package/lib/types/jsonrpc.d.ts.map +1 -0
- package/lib/types/jsonrpc.js +48 -0
- package/lib/types/jsonrpc.js.map +1 -0
- package/lib/types/outbound/calls.d.ts +37 -0
- package/lib/types/outbound/calls.d.ts.map +1 -0
- package/lib/types/outbound/calls.js +120 -0
- package/lib/types/outbound/calls.js.map +1 -0
- package/lib/types/outbound/registry.d.ts +102 -0
- package/lib/types/outbound/registry.d.ts.map +1 -0
- package/lib/types/outbound/registry.js +249 -0
- package/lib/types/outbound/registry.js.map +1 -0
- package/lib/types/outbound/tools.d.ts +30 -0
- package/lib/types/outbound/tools.d.ts.map +1 -0
- package/lib/types/outbound/tools.js +86 -0
- package/lib/types/outbound/tools.js.map +1 -0
- package/lib/types/protocol.d.ts +194 -0
- package/lib/types/protocol.d.ts.map +1 -0
- package/lib/types/protocol.js +78 -0
- package/lib/types/protocol.js.map +1 -0
- package/lib/types/server/a2a-server.d.ts +98 -0
- package/lib/types/server/a2a-server.d.ts.map +1 -0
- package/lib/types/server/a2a-server.js +397 -0
- package/lib/types/server/a2a-server.js.map +1 -0
- package/lib/types/server/card.d.ts +48 -0
- package/lib/types/server/card.d.ts.map +1 -0
- package/lib/types/server/card.js +75 -0
- package/lib/types/server/card.js.map +1 -0
- package/lib/types/server/exec/agent-runtime.d.ts +126 -0
- package/lib/types/server/exec/agent-runtime.d.ts.map +1 -0
- package/lib/types/server/exec/agent-runtime.js +138 -0
- package/lib/types/server/exec/agent-runtime.js.map +1 -0
- package/lib/types/server/exec/session.d.ts +11 -0
- package/lib/types/server/exec/session.d.ts.map +1 -0
- package/lib/types/server/exec/session.js +22 -0
- package/lib/types/server/exec/session.js.map +1 -0
- package/lib/types/server/exec/subagent.d.ts +39 -0
- package/lib/types/server/exec/subagent.d.ts.map +1 -0
- package/lib/types/server/exec/subagent.js +44 -0
- package/lib/types/server/exec/subagent.js.map +1 -0
- package/lib/types/server/executor.d.ts +63 -0
- package/lib/types/server/executor.d.ts.map +1 -0
- package/lib/types/server/executor.js +38 -0
- package/lib/types/server/executor.js.map +1 -0
- package/lib/types/server/routes.d.ts +32 -0
- package/lib/types/server/routes.d.ts.map +1 -0
- package/lib/types/server/routes.js +131 -0
- package/lib/types/server/routes.js.map +1 -0
- package/lib/types/server/store.d.ts +157 -0
- package/lib/types/server/store.d.ts.map +1 -0
- package/lib/types/server/store.js +239 -0
- package/lib/types/server/store.js.map +1 -0
- package/lib/types/service.d.ts +49 -0
- package/lib/types/service.d.ts.map +1 -0
- package/lib/types/service.js +46 -0
- package/lib/types/service.js.map +1 -0
- package/package.json +82 -0
- package/src/api.ts +115 -0
- package/src/client/index.ts +293 -0
- package/src/commands.ts +92 -0
- package/src/events.ts +58 -0
- package/src/index.ts +353 -0
- package/src/jsonrpc.ts +61 -0
- package/src/outbound/calls.ts +145 -0
- package/src/outbound/registry.ts +290 -0
- package/src/outbound/tools.ts +118 -0
- package/src/protocol.ts +212 -0
- package/src/server/a2a-server.ts +455 -0
- package/src/server/card.ts +106 -0
- package/src/server/exec/agent-runtime.ts +197 -0
- package/src/server/exec/session.ts +25 -0
- package/src/server/exec/subagent.ts +67 -0
- package/src/server/executor.ts +73 -0
- package/src/server/routes.ts +156 -0
- package/src/server/store.ts +320 -0
- package/src/service.ts +78 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound agent registry: the persisted list of connected remote agents,
|
|
3
|
+
* their connection state, and the tool-registration disposers for each live
|
|
4
|
+
* connection. Loaded at boot, mutations persist through the agent store.
|
|
5
|
+
* @module dsh-a2a/client/registry
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolRegistrar } from './tools.ts';
|
|
8
|
+
import { type OutboundAgentRecord } from '../server/store.ts';
|
|
9
|
+
/** User-supplied agent spec (from config or the /a2a command). */
|
|
10
|
+
export interface OutboundAgentSpec {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly agentCardUrl: string;
|
|
13
|
+
readonly bearerTokenEnv?: string;
|
|
14
|
+
readonly enabled?: boolean;
|
|
15
|
+
readonly timeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface OutboundAgentView {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly agentCardUrl: string;
|
|
21
|
+
readonly enabled: boolean;
|
|
22
|
+
readonly state: 'connected' | 'disconnected' | 'failed';
|
|
23
|
+
readonly skillCount: number;
|
|
24
|
+
readonly toolCount: number;
|
|
25
|
+
readonly lastError?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Durable store for the registry records. */
|
|
28
|
+
export interface AgentStore {
|
|
29
|
+
list(): OutboundAgentRecord[];
|
|
30
|
+
save(records: readonly OutboundAgentRecord[]): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/** In-memory agent store (tests and minimal embeddings). */
|
|
33
|
+
export declare class MemoryAgentStore implements AgentStore {
|
|
34
|
+
private records;
|
|
35
|
+
constructor(initial?: readonly OutboundAgentRecord[]);
|
|
36
|
+
list(): OutboundAgentRecord[];
|
|
37
|
+
save(records: readonly OutboundAgentRecord[]): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/** Domain-backed agent store: one JSON array under the `agents` table key. */
|
|
40
|
+
export declare class DomainAgentStore implements AgentStore {
|
|
41
|
+
private readonly table;
|
|
42
|
+
private static readonly KEY;
|
|
43
|
+
constructor(table: {
|
|
44
|
+
get(key: string): string | undefined;
|
|
45
|
+
put(key: string, value: string): Promise<void>;
|
|
46
|
+
});
|
|
47
|
+
list(): OutboundAgentRecord[];
|
|
48
|
+
save(records: readonly OutboundAgentRecord[]): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export interface RegistryOptions {
|
|
51
|
+
readonly registrar: ToolRegistrar;
|
|
52
|
+
readonly store: AgentStore;
|
|
53
|
+
readonly toolPrefix?: string;
|
|
54
|
+
readonly defaultTimeoutMs?: number;
|
|
55
|
+
/** Resolve a bearer token from an env-var name; undefined when unset. */
|
|
56
|
+
readonly tokenOf: (env: string | undefined) => string | undefined;
|
|
57
|
+
readonly onError?: (message: string) => void;
|
|
58
|
+
}
|
|
59
|
+
/** A list of remote agents, each with live tool registrations when enabled. */
|
|
60
|
+
export declare class OutboundAgentRegistry {
|
|
61
|
+
private readonly opts;
|
|
62
|
+
private readonly live;
|
|
63
|
+
private readonly views;
|
|
64
|
+
private seedRecords;
|
|
65
|
+
constructor(opts: RegistryOptions);
|
|
66
|
+
/** Load persisted records and connect every enabled agent (background). */
|
|
67
|
+
loadAll(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Seed configured agents that the persisted store does not know yet. The
|
|
70
|
+
* store is the runtime state: an existing record (enabled or disabled,
|
|
71
|
+
* present or removed) keeps its state — a disabled agent stays
|
|
72
|
+
* disconnected and a removed one is not resurrected. Only specs with a name
|
|
73
|
+
* absent from the store (and not already live this boot) connect and
|
|
74
|
+
* persist.
|
|
75
|
+
* @param specs - declared agents from the profile config.
|
|
76
|
+
*/
|
|
77
|
+
seed(specs: readonly OutboundAgentSpec[]): Promise<void>;
|
|
78
|
+
list(): OutboundAgentView[];
|
|
79
|
+
/** Add and connect an agent, persisting the record on success. */
|
|
80
|
+
add(spec: OutboundAgentSpec): Promise<{
|
|
81
|
+
ok: boolean;
|
|
82
|
+
message: string;
|
|
83
|
+
}>;
|
|
84
|
+
remove(id: string): Promise<{
|
|
85
|
+
ok: boolean;
|
|
86
|
+
message: string;
|
|
87
|
+
}>;
|
|
88
|
+
setEnabled(id: string, enabled: boolean): Promise<{
|
|
89
|
+
ok: boolean;
|
|
90
|
+
message: string;
|
|
91
|
+
}>;
|
|
92
|
+
refresh(id: string): Promise<{
|
|
93
|
+
ok: boolean;
|
|
94
|
+
message: string;
|
|
95
|
+
}>;
|
|
96
|
+
disposeAll(): Promise<void>;
|
|
97
|
+
private connectRecord;
|
|
98
|
+
private findRecord;
|
|
99
|
+
private persist;
|
|
100
|
+
private persistAll;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/outbound/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound agent registry: the persisted list of connected remote agents,
|
|
3
|
+
* their connection state, and the tool-registration disposers for each live
|
|
4
|
+
* connection. Loaded at boot, mutations persist through the agent store.
|
|
5
|
+
* @module dsh-a2a/client/registry
|
|
6
|
+
*/
|
|
7
|
+
import { A2AClient } from "./calls.js";
|
|
8
|
+
import { registerAgentTools } from "./tools.js";
|
|
9
|
+
/** In-memory agent store (tests and minimal embeddings). */
|
|
10
|
+
export class MemoryAgentStore {
|
|
11
|
+
records = [];
|
|
12
|
+
constructor(initial = []) {
|
|
13
|
+
this.records = [...initial];
|
|
14
|
+
}
|
|
15
|
+
list() {
|
|
16
|
+
return [...this.records];
|
|
17
|
+
}
|
|
18
|
+
async save(records) {
|
|
19
|
+
this.records = [...records];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Domain-backed agent store: one JSON array under the `agents` table key. */
|
|
23
|
+
export class DomainAgentStore {
|
|
24
|
+
table;
|
|
25
|
+
static KEY = 'records';
|
|
26
|
+
constructor(table) {
|
|
27
|
+
this.table = table;
|
|
28
|
+
}
|
|
29
|
+
list() {
|
|
30
|
+
const raw = this.table.get(DomainAgentStore.KEY);
|
|
31
|
+
if (raw === undefined)
|
|
32
|
+
return [];
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(raw);
|
|
35
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async save(records) {
|
|
42
|
+
await this.table.put(DomainAgentStore.KEY, JSON.stringify(records));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** A list of remote agents, each with live tool registrations when enabled. */
|
|
46
|
+
export class OutboundAgentRegistry {
|
|
47
|
+
opts;
|
|
48
|
+
live = new Map();
|
|
49
|
+
views = new Map();
|
|
50
|
+
seedRecords;
|
|
51
|
+
constructor(opts) {
|
|
52
|
+
this.opts = opts;
|
|
53
|
+
}
|
|
54
|
+
/** Load persisted records and connect every enabled agent (background). */
|
|
55
|
+
loadAll() {
|
|
56
|
+
const records = this.opts.store.list();
|
|
57
|
+
this.seedRecords = records;
|
|
58
|
+
for (const record of records) {
|
|
59
|
+
if (record.enabled)
|
|
60
|
+
void this.connectRecord(record).catch((err) => {
|
|
61
|
+
this.opts.onError?.(`[a2a] failed to connect "${record.name}": ${err.message}`);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Seed configured agents that the persisted store does not know yet. The
|
|
67
|
+
* store is the runtime state: an existing record (enabled or disabled,
|
|
68
|
+
* present or removed) keeps its state — a disabled agent stays
|
|
69
|
+
* disconnected and a removed one is not resurrected. Only specs with a name
|
|
70
|
+
* absent from the store (and not already live this boot) connect and
|
|
71
|
+
* persist.
|
|
72
|
+
* @param specs - declared agents from the profile config.
|
|
73
|
+
*/
|
|
74
|
+
async seed(specs) {
|
|
75
|
+
const known = new Set(this.opts.store.list().map((r) => r.name));
|
|
76
|
+
for (const connection of this.live.values())
|
|
77
|
+
known.add(connection.record.name);
|
|
78
|
+
for (const spec of specs) {
|
|
79
|
+
if (known.has(spec.name))
|
|
80
|
+
continue;
|
|
81
|
+
const result = await this.add(spec);
|
|
82
|
+
if (result.ok)
|
|
83
|
+
known.add(spec.name);
|
|
84
|
+
else
|
|
85
|
+
this.opts.onError?.(`[a2a] seed agent "${spec.name}": ${result.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
list() {
|
|
89
|
+
return [...this.views.values()];
|
|
90
|
+
}
|
|
91
|
+
/** Add and connect an agent, persisting the record on success. */
|
|
92
|
+
async add(spec) {
|
|
93
|
+
const record = {
|
|
94
|
+
id: `agent-${crypto.randomUUID()}`,
|
|
95
|
+
name: spec.name,
|
|
96
|
+
agentCardUrl: spec.agentCardUrl,
|
|
97
|
+
...(spec.bearerTokenEnv ? { bearerTokenEnv: spec.bearerTokenEnv } : {}),
|
|
98
|
+
enabled: spec.enabled ?? true,
|
|
99
|
+
timeoutMs: spec.timeoutMs ?? this.opts.defaultTimeoutMs ?? 60_000,
|
|
100
|
+
lastCardAt: null,
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
await this.connectRecord(record);
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
this.views.set(record.id, {
|
|
107
|
+
id: record.id,
|
|
108
|
+
name: record.name,
|
|
109
|
+
agentCardUrl: record.agentCardUrl,
|
|
110
|
+
enabled: record.enabled,
|
|
111
|
+
state: 'failed',
|
|
112
|
+
skillCount: 0,
|
|
113
|
+
toolCount: 0,
|
|
114
|
+
lastError: err.message,
|
|
115
|
+
});
|
|
116
|
+
return { ok: false, message: `failed to connect to ${record.agentCardUrl}: ${err.message}` };
|
|
117
|
+
}
|
|
118
|
+
this.persist(record);
|
|
119
|
+
return { ok: true, message: `agent "${record.name}" connected` };
|
|
120
|
+
}
|
|
121
|
+
async remove(id) {
|
|
122
|
+
const live = this.live.get(id);
|
|
123
|
+
const view = this.views.get(id);
|
|
124
|
+
if (live === undefined && view === undefined)
|
|
125
|
+
return { ok: false, message: `agent ${id} not found` };
|
|
126
|
+
for (const disposer of live?.disposers ?? [])
|
|
127
|
+
disposer.dispose();
|
|
128
|
+
this.live.delete(id);
|
|
129
|
+
this.views.delete(id);
|
|
130
|
+
await this.persistAll();
|
|
131
|
+
return { ok: true, message: `agent ${id} removed` };
|
|
132
|
+
}
|
|
133
|
+
async setEnabled(id, enabled) {
|
|
134
|
+
const live = this.live.get(id);
|
|
135
|
+
const view = this.views.get(id);
|
|
136
|
+
if (live === undefined && view === undefined)
|
|
137
|
+
return { ok: false, message: `agent ${id} not found` };
|
|
138
|
+
if (enabled && live === undefined) {
|
|
139
|
+
const record = this.findRecord(id);
|
|
140
|
+
if (record === undefined)
|
|
141
|
+
return { ok: false, message: `agent ${id} has no persisted record` };
|
|
142
|
+
try {
|
|
143
|
+
await this.connectRecord(record);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
return { ok: false, message: `failed to connect: ${err.message}` };
|
|
147
|
+
}
|
|
148
|
+
await this.persistAll();
|
|
149
|
+
return { ok: true, message: `agent ${id} enabled` };
|
|
150
|
+
}
|
|
151
|
+
if (!enabled && live !== undefined) {
|
|
152
|
+
for (const disposer of live.disposers)
|
|
153
|
+
disposer.dispose();
|
|
154
|
+
this.live.delete(id);
|
|
155
|
+
const current = this.views.get(id);
|
|
156
|
+
if (current !== undefined) {
|
|
157
|
+
this.views.set(id, { ...current, enabled: false, state: 'disconnected', toolCount: 0, skillCount: 0 });
|
|
158
|
+
}
|
|
159
|
+
await this.persistAll();
|
|
160
|
+
return { ok: true, message: `agent ${id} disabled` };
|
|
161
|
+
}
|
|
162
|
+
return { ok: true, message: `agent ${id} already ${enabled ? 'enabled' : 'disabled'}` };
|
|
163
|
+
}
|
|
164
|
+
async refresh(id) {
|
|
165
|
+
const record = this.findRecord(id) ?? this.live.get(id)?.record;
|
|
166
|
+
if (record === undefined)
|
|
167
|
+
return { ok: false, message: `agent ${id} not found` };
|
|
168
|
+
const live = this.live.get(id);
|
|
169
|
+
for (const disposer of live?.disposers ?? [])
|
|
170
|
+
disposer.dispose();
|
|
171
|
+
this.live.delete(id);
|
|
172
|
+
try {
|
|
173
|
+
await this.connectRecord(record);
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
return { ok: false, message: `refresh failed: ${err.message}` };
|
|
177
|
+
}
|
|
178
|
+
await this.persistAll();
|
|
179
|
+
return { ok: true, message: `agent "${record.name}" reconnected` };
|
|
180
|
+
}
|
|
181
|
+
async disposeAll() {
|
|
182
|
+
for (const connection of this.live.values()) {
|
|
183
|
+
for (const disposer of connection.disposers)
|
|
184
|
+
disposer.dispose();
|
|
185
|
+
}
|
|
186
|
+
this.live.clear();
|
|
187
|
+
this.views.clear();
|
|
188
|
+
}
|
|
189
|
+
async connectRecord(record) {
|
|
190
|
+
const token = this.opts.tokenOf(record.bearerTokenEnv);
|
|
191
|
+
const client = await A2AClient.connect(record.agentCardUrl, {
|
|
192
|
+
...(token ? { bearerToken: token } : {}),
|
|
193
|
+
timeoutMs: record.timeoutMs,
|
|
194
|
+
});
|
|
195
|
+
const contextByAgent = new Map();
|
|
196
|
+
const fallback = `a2a-out-${crypto.randomUUID()}`;
|
|
197
|
+
const contextFor = (agentId) => {
|
|
198
|
+
const key = agentId ?? '\0fallback';
|
|
199
|
+
const existing = contextByAgent.get(key);
|
|
200
|
+
if (existing !== undefined)
|
|
201
|
+
return existing;
|
|
202
|
+
const id = agentId ? `a2a-out-${crypto.randomUUID()}` : fallback;
|
|
203
|
+
contextByAgent.set(key, id);
|
|
204
|
+
return id;
|
|
205
|
+
};
|
|
206
|
+
const disposers = registerAgentTools(this.opts.registrar, {
|
|
207
|
+
agentName: record.name,
|
|
208
|
+
client,
|
|
209
|
+
...(this.opts.toolPrefix !== undefined ? { toolPrefix: this.opts.toolPrefix } : {}),
|
|
210
|
+
contextFor,
|
|
211
|
+
});
|
|
212
|
+
const skillCount = client.card.skills?.length ?? 0;
|
|
213
|
+
this.live.set(record.id, { record, client, disposers, skillCount });
|
|
214
|
+
this.views.set(record.id, {
|
|
215
|
+
id: record.id,
|
|
216
|
+
name: record.name,
|
|
217
|
+
agentCardUrl: record.agentCardUrl,
|
|
218
|
+
enabled: record.enabled,
|
|
219
|
+
state: 'connected',
|
|
220
|
+
skillCount,
|
|
221
|
+
toolCount: disposers.length,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
findRecord(id) {
|
|
225
|
+
const current = () => this.opts.store.list().find((r) => r.id === id);
|
|
226
|
+
return current() ?? this.seedRecords?.find((r) => r.id === id);
|
|
227
|
+
}
|
|
228
|
+
persist(record) {
|
|
229
|
+
const next = [...this.opts.store.list().filter((r) => r.id !== record.id), record];
|
|
230
|
+
void this.opts.store.save(next).catch((err) => {
|
|
231
|
+
this.opts.onError?.(`[a2a] failed to persist agent list: ${String(err)}`);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
async persistAll() {
|
|
235
|
+
const liveRecords = [...this.live.values()].map((c) => c.record);
|
|
236
|
+
const liveIds = new Set(liveRecords.map((r) => r.id));
|
|
237
|
+
// Non-live known records (disabled agents) keep the store record with the
|
|
238
|
+
// view's up-to-date enabled flag; removed agents (gone from live AND
|
|
239
|
+
// views) are dropped so a restart does not resurrect them.
|
|
240
|
+
const kept = this.opts.store.list()
|
|
241
|
+
.filter((r) => !liveIds.has(r.id) && this.views.has(r.id))
|
|
242
|
+
.map((r) => {
|
|
243
|
+
const view = this.views.get(r.id);
|
|
244
|
+
return view === undefined ? r : { ...r, enabled: view.enabled };
|
|
245
|
+
});
|
|
246
|
+
await this.opts.store.save([...kept, ...liveRecords]);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/outbound/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound half: register one remote agent's skills as model-facing tools on
|
|
3
|
+
* `ctx.tools`. Tool names are `a2a__<agent>__<skill>` normalized to the DSH
|
|
4
|
+
* function-name contract (≤64 chars, collision hash), mirroring the naming
|
|
5
|
+
* rule of dsh-mcp-client. An agent advertising zero skills registers nothing.
|
|
6
|
+
* @module dsh-a2a/client/tools
|
|
7
|
+
*/
|
|
8
|
+
import { type A2AClient } from './calls.ts';
|
|
9
|
+
/** Structural slice of `ctx.tools` used for registration. */
|
|
10
|
+
export interface ToolRegistrar {
|
|
11
|
+
register(definition: unknown): (() => void) | void;
|
|
12
|
+
}
|
|
13
|
+
export interface AgentToolsOptions {
|
|
14
|
+
readonly agentName: string;
|
|
15
|
+
readonly client: A2AClient;
|
|
16
|
+
/** Tool prefix; default 'a2a'. */
|
|
17
|
+
readonly toolPrefix?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the remote conversation contextId for one calling local agent
|
|
20
|
+
* (stable per caller, so multi-turn tool use is one remote conversation).
|
|
21
|
+
*/
|
|
22
|
+
readonly contextFor: (agentId: string | undefined) => string;
|
|
23
|
+
}
|
|
24
|
+
export interface RegisteredTool {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
/** Register one tool per advertised skill; empty skills register nothing. */
|
|
29
|
+
export declare function registerAgentTools(registrar: ToolRegistrar, opts: AgentToolsOptions): RegisteredTool[];
|
|
30
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/outbound/tools.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAErD,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;CACnD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAA;CAC7D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,IAAI,IAAI,CAAA;CAChB;AAUD,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,GAAG,cAAc,EAAE,CAiBtG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound half: register one remote agent's skills as model-facing tools on
|
|
3
|
+
* `ctx.tools`. Tool names are `a2a__<agent>__<skill>` normalized to the DSH
|
|
4
|
+
* function-name contract (≤64 chars, collision hash), mirroring the naming
|
|
5
|
+
* rule of dsh-mcp-client. An agent advertising zero skills registers nothing.
|
|
6
|
+
* @module dsh-a2a/client/tools
|
|
7
|
+
*/
|
|
8
|
+
import { Role, partsToText } from "../protocol.js";
|
|
9
|
+
import { A2AError } from "./calls.js";
|
|
10
|
+
function normalizeToolName(raw) {
|
|
11
|
+
const norm = raw.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 64);
|
|
12
|
+
if (norm.length > 0 && /^[A-Za-z0-9_-]+$/.test(norm))
|
|
13
|
+
return norm;
|
|
14
|
+
let hash = 0;
|
|
15
|
+
for (let i = 0; i < raw.length; i++)
|
|
16
|
+
hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;
|
|
17
|
+
return `_${hash.toString(16)}`;
|
|
18
|
+
}
|
|
19
|
+
/** Register one tool per advertised skill; empty skills register nothing. */
|
|
20
|
+
export function registerAgentTools(registrar, opts) {
|
|
21
|
+
const prefix = opts.toolPrefix ?? 'a2a';
|
|
22
|
+
const skills = opts.client.card.skills ?? [];
|
|
23
|
+
const out = [];
|
|
24
|
+
for (const skill of skills) {
|
|
25
|
+
const raw = `${prefix}__${opts.agentName}__${skill.id}`;
|
|
26
|
+
const name = normalizeToolName(raw);
|
|
27
|
+
let toolName = name;
|
|
28
|
+
if (out.some((t) => t.name === toolName)) {
|
|
29
|
+
let hash = 0;
|
|
30
|
+
for (let i = 0; i < raw.length; i++)
|
|
31
|
+
hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;
|
|
32
|
+
toolName = `${name.slice(0, 56)}_${hash.toString(16)}`;
|
|
33
|
+
}
|
|
34
|
+
const dispose = registrar.register(makeTool(toolName, opts.client, skill, opts.contextFor));
|
|
35
|
+
if (dispose)
|
|
36
|
+
out.push({ name: toolName, dispose });
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
function makeTool(name, client, skill, contextFor) {
|
|
41
|
+
const description = [
|
|
42
|
+
skill.description,
|
|
43
|
+
...(skill.examples?.length ? [`Examples: ${skill.examples.join(' | ')}`] : []),
|
|
44
|
+
].filter(Boolean).join('\n');
|
|
45
|
+
return {
|
|
46
|
+
name,
|
|
47
|
+
description,
|
|
48
|
+
parameters: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
prompt: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'The task or instruction to send to the remote agent.',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: ['prompt'],
|
|
57
|
+
},
|
|
58
|
+
output: {
|
|
59
|
+
schema: { type: 'string' },
|
|
60
|
+
render: (_args, value) => [{ type: 'text', text: String(value) }],
|
|
61
|
+
},
|
|
62
|
+
async execute(args, exec) {
|
|
63
|
+
const message = {
|
|
64
|
+
messageId: crypto.randomUUID(),
|
|
65
|
+
role: Role.USER,
|
|
66
|
+
contextId: contextFor(exec.agent?.id),
|
|
67
|
+
parts: [{ text: args.prompt }],
|
|
68
|
+
};
|
|
69
|
+
const task = await client.sendMessage(message);
|
|
70
|
+
return textOf(task.artifacts, task.status.state, task.status.message?.parts);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Render a settled task's output as tool text (INPUT_REQUIRED surfaced, not thrown). */
|
|
75
|
+
function textOf(artifacts, state, statusParts) {
|
|
76
|
+
const output = partsToText(artifacts?.flatMap((a) => a.parts ?? []));
|
|
77
|
+
if (state === 'FAILED') {
|
|
78
|
+
throw new A2AError(-32000, `Remote agent task failed: ${output || partsToText(statusParts) || 'no detail'}`);
|
|
79
|
+
}
|
|
80
|
+
if (state === 'INPUT_REQUIRED' || state === 'AUTH_REQUIRED') {
|
|
81
|
+
const ask = partsToText(statusParts) || output || 'agent awaits input';
|
|
82
|
+
return `[remote agent ${state}] ${ask}`;
|
|
83
|
+
}
|
|
84
|
+
return output || '(remote agent returned no output)';
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/outbound/tools.ts"],"names":[],"mappings":"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"}
|